diff --git a/src/id/mangakane/AndroidManifest.xml b/src/id/mangakane/AndroidManifest.xml
new file mode 100644
index 000000000..30deb7f79
--- /dev/null
+++ b/src/id/mangakane/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/src/id/mangakane/build.gradle b/src/id/mangakane/build.gradle
new file mode 100644
index 000000000..d5eec75a2
--- /dev/null
+++ b/src/id/mangakane/build.gradle
@@ -0,0 +1,12 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+
+ext {
+ extName = 'MangaKane'
+ pkgNameSuffix = 'id.mangakane'
+ extClass = '.MangaKane'
+ extVersionCode = 1
+ libVersion = '1.2'
+}
+
+apply from: "$rootDir/common.gradle"
diff --git a/src/id/mangakane/res/mipmap-hdpi/ic_launcher.png b/src/id/mangakane/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 000000000..584f56eae
Binary files /dev/null and b/src/id/mangakane/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/src/id/mangakane/res/mipmap-mdpi/ic_launcher.png b/src/id/mangakane/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 000000000..aa1956569
Binary files /dev/null and b/src/id/mangakane/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/src/id/mangakane/res/mipmap-xhdpi/ic_launcher.png b/src/id/mangakane/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 000000000..38855617a
Binary files /dev/null and b/src/id/mangakane/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/src/id/mangakane/res/mipmap-xxhdpi/ic_launcher.png b/src/id/mangakane/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 000000000..fa62341d4
Binary files /dev/null and b/src/id/mangakane/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/src/id/mangakane/res/mipmap-xxxhdpi/ic_launcher.png b/src/id/mangakane/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 000000000..024858a1f
Binary files /dev/null and b/src/id/mangakane/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/src/id/mangakane/res/web_hi_res_512.png b/src/id/mangakane/res/web_hi_res_512.png
new file mode 100644
index 000000000..ecafd7dbc
Binary files /dev/null and b/src/id/mangakane/res/web_hi_res_512.png differ
diff --git a/src/id/mangakane/src/eu/kanade/tachiyomi/extension/id/mangakane/MangaKane.kt b/src/id/mangakane/src/eu/kanade/tachiyomi/extension/id/mangakane/MangaKane.kt
new file mode 100644
index 000000000..522098571
--- /dev/null
+++ b/src/id/mangakane/src/eu/kanade/tachiyomi/extension/id/mangakane/MangaKane.kt
@@ -0,0 +1,102 @@
+package eu.kanade.tachiyomi.extension.id.mangakane
+
+import eu.kanade.tachiyomi.network.GET
+import eu.kanade.tachiyomi.source.model.FilterList
+import eu.kanade.tachiyomi.source.model.Page
+import eu.kanade.tachiyomi.source.model.SChapter
+import eu.kanade.tachiyomi.source.model.SManga
+import eu.kanade.tachiyomi.source.online.ParsedHttpSource
+import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
+import okhttp3.Request
+import org.jsoup.nodes.Document
+import org.jsoup.nodes.Element
+import java.text.SimpleDateFormat
+import java.util.Locale
+
+class MangaKane : ParsedHttpSource() {
+
+ override val name = "MangaKane"
+ override val baseUrl = "https://mangakane.com"
+ override val lang = "id"
+ override val supportsLatest = true
+
+ override fun popularMangaRequest(page: Int): Request {
+ return GET("$baseUrl/series/page/$page", headers)
+ }
+
+ override fun latestUpdatesRequest(page: Int): Request {
+ return GET("$baseUrl/page/$page", headers)
+ }
+
+ override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
+ val url = "$baseUrl/page/$page/?".toHttpUrlOrNull()!!.newBuilder()
+ .addQueryParameter("s", query)
+ return GET(url.toString(), headers)
+ }
+
+ override fun popularMangaSelector() = ".container .flexbox2 .flexbox2-item"
+ override fun latestUpdatesSelector() = "h2:not(:has(a)) + .flexbox3 .flexbox3-item"
+ override fun searchMangaSelector() = popularMangaSelector()
+
+ override fun popularMangaFromElement(element: Element): SManga {
+ val manga = SManga.create()
+ manga.setUrlWithoutDomain(element.select("a").attr("href"))
+ manga.title = element.select("a").attr("title")
+ manga.thumbnail_url = element.select("a img").attr("abs:src")
+
+ return manga
+ }
+
+ override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element)
+ override fun latestUpdatesFromElement(element: Element): SManga = popularMangaFromElement(element)
+
+ override fun popularMangaNextPageSelector() = ".pagination .next"
+ override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
+ override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
+
+ override fun mangaDetailsParse(document: Document) = SManga.create().apply {
+ author = document.select(".series-infolist li:contains(Author) span").text()
+ artist = document.select(".series-infolist li:contains(Artist) span").text()
+ status = parseStatus(document.select(".series-infoz .status").firstOrNull()?.ownText())
+ description = document.select(".series-synops p").text()
+ genre = document.select(".series-genres a").joinToString { it.text() }
+ }
+
+ protected fun parseStatus(element: String?): Int = when {
+ element == null -> SManga.UNKNOWN
+ listOf("ongoing", "publishing").any { it.contains(element, ignoreCase = true) } -> SManga.ONGOING
+ listOf("completed").any { it.contains(element, ignoreCase = true) } -> SManga.COMPLETED
+ else -> SManga.UNKNOWN
+ }
+
+ override fun chapterListSelector() = ".series-chapterlist li"
+
+ override fun chapterFromElement(element: Element) = SChapter.create().apply {
+ setUrlWithoutDomain(element.select(".flexch-infoz a").attr("href"))
+ name = element.select(".flexch-infoz span:not(.date)").first().ownText()
+ date_upload = parseChapterDate(element.select(".flexch-infoz .date").text()) ?: 0
+ }
+
+ private fun parseChapterDate(date: String): Long {
+ var parsedDate = 0L
+ try {
+ parsedDate = SimpleDateFormat("MMM dd, yyyy", Locale.US).parse(date)?.time ?: 0L
+ } catch (_: Exception) { /*nothing to do, parsedDate is initialized with 0L*/ }
+ return parsedDate
+ }
+
+ override fun pageListParse(document: Document): List {
+ val pages = mutableListOf()
+ var i = 0
+ document.select(".reader-area img").forEach { element ->
+ val url = element.attr("abs:src")
+ i++
+ if (url.isNotEmpty()) {
+ pages.add(Page(i, "", url))
+ }
+ }
+ return pages
+ }
+
+ override fun imageUrlParse(document: Document) = ""
+}