diff --git a/src/en/rawmanga/AndroidManifest.xml b/src/en/rawmanga/AndroidManifest.xml
new file mode 100644
index 000000000..30deb7f79
--- /dev/null
+++ b/src/en/rawmanga/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/src/en/rawmanga/build.gradle b/src/en/rawmanga/build.gradle
new file mode 100644
index 000000000..468ae49af
--- /dev/null
+++ b/src/en/rawmanga/build.gradle
@@ -0,0 +1,11 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+
+ext {
+ extName = 'Raw-Manga'
+ pkgNameSuffix = 'en.rawmanga'
+ extClass = '.RawManga'
+ extVersionCode = 1
+}
+
+apply from: "$rootDir/common.gradle"
diff --git a/src/en/rawmanga/res/mipmap-hdpi/ic_launcher.png b/src/en/rawmanga/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 000000000..d873e9a16
Binary files /dev/null and b/src/en/rawmanga/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/src/en/rawmanga/res/mipmap-mdpi/ic_launcher.png b/src/en/rawmanga/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 000000000..ce6ad014c
Binary files /dev/null and b/src/en/rawmanga/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/src/en/rawmanga/res/mipmap-xhdpi/ic_launcher.png b/src/en/rawmanga/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 000000000..716197742
Binary files /dev/null and b/src/en/rawmanga/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/src/en/rawmanga/res/mipmap-xxhdpi/ic_launcher.png b/src/en/rawmanga/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 000000000..af0d495f0
Binary files /dev/null and b/src/en/rawmanga/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/src/en/rawmanga/res/mipmap-xxxhdpi/ic_launcher.png b/src/en/rawmanga/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 000000000..ee179b8b5
Binary files /dev/null and b/src/en/rawmanga/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/src/en/rawmanga/res/web_hi_res_512.png b/src/en/rawmanga/res/web_hi_res_512.png
new file mode 100644
index 000000000..6373f6118
Binary files /dev/null and b/src/en/rawmanga/res/web_hi_res_512.png differ
diff --git a/src/en/rawmanga/src/eu/kanade/tachiyomi/extension/en/rawmanga/RawManga.kt b/src/en/rawmanga/src/eu/kanade/tachiyomi/extension/en/rawmanga/RawManga.kt
new file mode 100644
index 000000000..417767a16
--- /dev/null
+++ b/src/en/rawmanga/src/eu/kanade/tachiyomi/extension/en/rawmanga/RawManga.kt
@@ -0,0 +1,152 @@
+package eu.kanade.tachiyomi.extension.en.rawmanga
+
+import eu.kanade.tachiyomi.network.GET
+import eu.kanade.tachiyomi.source.model.FilterList
+import eu.kanade.tachiyomi.source.model.MangasPage
+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 eu.kanade.tachiyomi.util.asJsoup
+import okhttp3.Request
+import okhttp3.Response
+import org.jsoup.nodes.Document
+import org.jsoup.nodes.Element
+import java.text.SimpleDateFormat
+import java.util.Locale
+
+class RawManga : ParsedHttpSource() {
+
+ override val name = "Raw-Manga"
+ override val baseUrl = "https://raw-manga.org"
+ override val lang = "en"
+ override val supportsLatest = true
+
+ // Popular Manga
+
+ override fun popularMangaRequest(page: Int): Request {
+ return GET("$baseUrl/pieces/pages.php?orderedpage=$page")
+ }
+
+ override fun popularMangaSelector(): String = ".mangalistcnt"
+
+ override fun popularMangaNextPageSelector(): String = "#paginationcontainer a:contains(Last Page)"
+
+ override fun popularMangaFromElement(element: Element): SManga {
+ return SManga.create().apply {
+ url = element.selectFirst("div > a").attr("href")
+ title = element.select("div > a > h2").text().trim()
+ thumbnail_url = element.select("a > div > img").attr("src")
+ }
+ }
+
+ // Latest Updates
+
+ override fun latestUpdatesSelector(): String = ".updatescontainer"
+
+ override fun latestUpdatesFromElement(element: Element): SManga {
+ return SManga.create().apply {
+ url = element.select(".mangatitle").attr("href")
+ title = element.select(".mangatitle").text().trim()
+ thumbnail_url = element.select("div > a > img").attr("src")
+ }
+ }
+
+ override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/updates.php?page=$page)", headers)
+
+ override fun latestUpdatesParse(response: Response): MangasPage {
+ val document = response.asJsoup()
+
+ val mangas = document.select(latestUpdatesSelector()).map { element ->
+ latestUpdatesFromElement(element)
+ }
+
+ return MangasPage(mangas, mangas.size == 60)
+ }
+
+ // Manga Details Parse
+
+ override fun mangaDetailsParse(document: Document): SManga {
+ return SManga.create().apply {
+ thumbnail_url = document.select(".img-thumbnail").attr("src")
+ title = document.select("#mangaholder h1").text().trim()
+ description = document.selectFirst("#info p").text()
+ .replace(Regex("^(.*?)This Comic is About"), "").trim() // Removing boilerplate text
+ author = document.selectFirst("#titlecompenents dt").text().trim()
+ genre = document.select("#titlecompenents li").text().trim()
+ status = when (document.select("#titlecompenents dt:nth-of-type(2)").text().trim()) {
+ "Ongoing" -> SManga.ONGOING
+ "Completed" -> SManga.COMPLETED
+ else -> SManga.UNKNOWN
+ }
+ }
+ }
+
+ // Chapter List
+
+ override fun chapterListSelector(): String = "tbody tr"
+
+ override fun chapterListParse(response: Response): List {
+ val mangaId = response.asJsoup().selectFirst(".btn-danger").attr("onclick")
+ .substringAfter("(").substringBefore(")")
+
+ val chapters = client.newCall(GET("$baseUrl/pieces/chaps.php?mng=$mangaId", headers)).execute()
+
+ return chapters.asJsoup().select(chapterListSelector())
+ .map {
+ SChapter.create().apply {
+ url = it.select("a").attr("href").trim()
+ name = "Chapter " + it.text().trim().split(" ")[1]
+ chapter_number = it.text().trim().split(" ")[1].toFloat()
+ date_upload = it.select("td:last-of-type").text().trim()
+ .let { DATE_FORMATTER.parse(it)?.time ?: 0L }
+ }
+ }
+ }
+
+ // Page
+
+ override fun pageListParse(document: Document): List {
+ return document.select("#chapcontainer .imgholder").mapIndexed { index, element ->
+ Page(index, "", element.attr("src"))
+ }
+ }
+
+ // Search
+ // advanced.php supports filters via POST, but has no title search
+ override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
+ return GET("$baseUrl/search.php?manga=$query", headers)
+ }
+
+ override fun searchMangaSelector(): String = "a"
+
+ override fun searchMangaFromElement(element: Element): SManga {
+ return SManga.create().apply {
+ url = element.attr("href").trim()
+ title = element.select("li").text().trim()
+ thumbnail_url = "https://readmanganow.com/images/thumbnails/$title.webp" // Works for most
+ }
+ }
+
+ override fun searchMangaParse(response: Response): MangasPage {
+ val document = response.asJsoup()
+
+ val mangas = document.select(searchMangaSelector()).map { element ->
+ searchMangaFromElement(element)
+ }
+
+ return MangasPage(mangas, false)
+ }
+
+ override fun latestUpdatesNextPageSelector() = throw java.lang.UnsupportedOperationException("Not used.")
+
+ override fun chapterFromElement(element: Element): SChapter = throw UnsupportedOperationException("Not used.")
+
+ override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used.")
+
+ override fun searchMangaNextPageSelector(): String = throw UnsupportedOperationException("Not used.")
+
+ companion object {
+ val DATE_FORMATTER by lazy { SimpleDateFormat("yyyy-MM-dd", Locale.US) }
+ }
+}