diff --git a/src/en/reallifecomics/AndroidManifest.xml b/src/en/reallifecomics/AndroidManifest.xml
new file mode 100644
index 000000000..30deb7f79
--- /dev/null
+++ b/src/en/reallifecomics/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/src/en/reallifecomics/build.gradle b/src/en/reallifecomics/build.gradle
new file mode 100644
index 000000000..7a562313d
--- /dev/null
+++ b/src/en/reallifecomics/build.gradle
@@ -0,0 +1,16 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+
+ext {
+ extName = 'Real Life Comics'
+ pkgNameSuffix = 'en.reallifecomics'
+ extClass = '.RealLifeComics'
+ extVersionCode = 1
+ libVersion = '1.2'
+}
+
+dependencies {
+ // implementation project(':lib-ratelimit')
+}
+
+apply from: "$rootDir/common.gradle"
diff --git a/src/en/reallifecomics/res/mipmap-anydpi-v26/ic_launcher.xml b/src/en/reallifecomics/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 000000000..036d09bc5
--- /dev/null
+++ b/src/en/reallifecomics/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/en/reallifecomics/res/mipmap-anydpi-v26/ic_launcher_round.xml b/src/en/reallifecomics/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 000000000..036d09bc5
--- /dev/null
+++ b/src/en/reallifecomics/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/en/reallifecomics/res/mipmap-hdpi/ic_launcher_foreground.png b/src/en/reallifecomics/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 000000000..17728005a
Binary files /dev/null and b/src/en/reallifecomics/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/src/en/reallifecomics/res/mipmap-mdpi/ic_launcher_foreground.png b/src/en/reallifecomics/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 000000000..7e836fae7
Binary files /dev/null and b/src/en/reallifecomics/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/src/en/reallifecomics/res/mipmap-xhdpi/ic_launcher_foreground.png b/src/en/reallifecomics/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 000000000..6ef62bc25
Binary files /dev/null and b/src/en/reallifecomics/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/src/en/reallifecomics/res/mipmap-xxhdpi/ic_launcher_foreground.png b/src/en/reallifecomics/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 000000000..2955332ba
Binary files /dev/null and b/src/en/reallifecomics/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/src/en/reallifecomics/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/src/en/reallifecomics/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 000000000..bc0813ff3
Binary files /dev/null and b/src/en/reallifecomics/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/src/en/reallifecomics/res/values/ic_launcher_background.xml b/src/en/reallifecomics/res/values/ic_launcher_background.xml
new file mode 100644
index 000000000..c5d5899fd
--- /dev/null
+++ b/src/en/reallifecomics/res/values/ic_launcher_background.xml
@@ -0,0 +1,4 @@
+
+
+ #FFFFFF
+
\ No newline at end of file
diff --git a/src/en/reallifecomics/res/web_hi_res_512.png b/src/en/reallifecomics/res/web_hi_res_512.png
new file mode 100644
index 000000000..82a6d5610
Binary files /dev/null and b/src/en/reallifecomics/res/web_hi_res_512.png differ
diff --git a/src/en/reallifecomics/src/eu/kanade/tachiyomi/extension/en/reallifecomics/RealLifeComics.kt b/src/en/reallifecomics/src/eu/kanade/tachiyomi/extension/en/reallifecomics/RealLifeComics.kt
new file mode 100644
index 000000000..1682a767a
--- /dev/null
+++ b/src/en/reallifecomics/src/eu/kanade/tachiyomi/extension/en/reallifecomics/RealLifeComics.kt
@@ -0,0 +1,143 @@
+package eu.kanade.tachiyomi.extension.en.reallifecomics
+
+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 okhttp3.Response
+import org.jsoup.nodes.Document
+import org.jsoup.nodes.Element
+import rx.Observable
+import java.text.SimpleDateFormat
+import java.util.Calendar
+import java.util.Locale
+
+class RealLifeComics : ParsedHttpSource() {
+ override val name = "Real Life Comics"
+
+ override val baseUrl = "https://reallifecomics.com"
+
+ override val lang = "en"
+
+ override val supportsLatest = false
+
+ // Helper
+
+ private fun createManga(year: Int): SManga = SManga.create().apply {
+ setUrlWithoutDomain("/archivepage.php?year=$year")
+ title = "$name ($year)"
+ thumbnail_url = "$baseUrl$LOGO"
+ author = AUTHOR
+ status = if (year != currentYear) SManga.COMPLETED else SManga.ONGOING
+ description = "$SUMMARY $year"
+ }
+
+ // Popular
+
+ override fun fetchPopularManga(page: Int): Observable {
+ // create one manga entry for each yearly archive
+ // skip 2016 and 2017 as they don't have any archive
+ return (currentYear downTo 1999).filter { it !in 2016..2017 }
+ .map { createManga(it) }
+ .let { Observable.just(MangasPage(it, false))!! }
+ }
+
+ // Search
+
+ override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable =
+ fetchPopularManga(1).map { mangaList ->
+ mangaList.copy(mangaList.mangas.filter { it.title.contains(query) })
+ }
+
+ // Details
+
+ override fun fetchMangaDetails(manga: SManga) = Observable.just(
+ manga.apply {
+ initialized = true
+ }
+ )!!
+
+ // Chapters
+
+ override fun chapterListParse(response: Response): List {
+ return super.chapterListParse(response).distinct().mapIndexed { index, chapter ->
+ chapter.apply { chapter_number = index.toFloat() }
+ }
+ }
+
+ override fun chapterListSelector() = ".calendar tbody tr td a"
+
+ override fun chapterFromElement(element: Element) = SChapter.create().apply {
+ url = element.attr("href")
+
+ // entries between 1999-2014 do not have dates in the link
+ // but all entries are placed in a calendar class which has the month & year as heading
+ // figure out a date using the calendar
+ // perhaps there might be a better way to get this but for now this works
+ val monthYear = element
+ .parent()
+ .parent()
+ .parent()
+ .parent()
+ .firstElementSibling()
+ .text()
+
+ val date = "$monthYear ${element.text()}"
+ val parsedDate = SimpleDateFormat("MMMM yyyy dd", Locale.US).parse(date)
+ date_upload = parsedDate?.time ?: 0L
+
+ // chapter names are kept the same as what the site has
+ name = SimpleDateFormat("EEEE, MMM dd, yyyy", Locale.US).format(parsedDate ?: 0L)
+ }
+
+ // Page
+
+ override fun pageListParse(document: Document): List {
+ val image = document.select(".comic img").attr("src")
+ return listOf(Page(0, "", image))
+ }
+
+ // Unsupported
+
+ override fun imageUrlParse(document: Document) = throw Exception("Not used")
+
+ override fun popularMangaSelector() = throw Exception("Not used")
+
+ override fun searchMangaFromElement(element: Element) = throw Exception("Not used")
+
+ override fun searchMangaNextPageSelector() = throw Exception("Not used")
+
+ override fun searchMangaSelector() = throw Exception("Not used")
+
+ override fun popularMangaRequest(page: Int) = throw Exception("Not used")
+
+ override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = throw Exception("Not used")
+
+ override fun popularMangaNextPageSelector() = throw Exception("Not used")
+
+ override fun popularMangaFromElement(element: Element) = throw Exception("Not used")
+
+ override fun mangaDetailsParse(document: Document) = throw Exception("Not used")
+
+ override fun latestUpdatesNextPageSelector() = throw Exception("Not used")
+
+ override fun latestUpdatesFromElement(element: Element) = throw Exception("Not used")
+
+ override fun latestUpdatesRequest(page: Int) = throw Exception("Not used")
+
+ override fun latestUpdatesSelector() = throw Exception("Not used")
+
+ companion object {
+ private const val LOGO = "/images/logo.png"
+
+ private const val AUTHOR = "Maelyn Dean"
+
+ private const val SUMMARY = "The normal daily lives of some abnormal people. This entry includes all the chapters published in"
+
+ private val currentYear by lazy {
+ Calendar.getInstance()[Calendar.YEAR]
+ }
+ }
+}