diff --git a/src/en/irovedout/AndroidManifest.xml b/src/en/irovedout/AndroidManifest.xml
new file mode 100644
index 000000000..b4571bfa8
--- /dev/null
+++ b/src/en/irovedout/AndroidManifest.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/src/en/irovedout/build.gradle b/src/en/irovedout/build.gradle
new file mode 100644
index 000000000..88484283b
--- /dev/null
+++ b/src/en/irovedout/build.gradle
@@ -0,0 +1,12 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+
+ext {
+ extName = 'I Roved Out'
+ pkgNameSuffix = 'en.irovedout'
+ extClass = '.IRovedOut'
+ extVersionCode = 1
+ isNsfw = true
+}
+
+apply from: "$rootDir/common.gradle"
diff --git a/src/en/irovedout/res/mipmap-hdpi/ic_launcher.png b/src/en/irovedout/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 000000000..23a83e125
Binary files /dev/null and b/src/en/irovedout/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/src/en/irovedout/res/mipmap-mdpi/ic_launcher.png b/src/en/irovedout/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 000000000..e4c61108b
Binary files /dev/null and b/src/en/irovedout/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/src/en/irovedout/res/mipmap-xhdpi/ic_launcher.png b/src/en/irovedout/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 000000000..1e2ab3ccf
Binary files /dev/null and b/src/en/irovedout/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/src/en/irovedout/res/mipmap-xxhdpi/ic_launcher.png b/src/en/irovedout/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 000000000..423aacc9d
Binary files /dev/null and b/src/en/irovedout/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/src/en/irovedout/res/mipmap-xxxhdpi/ic_launcher.png b/src/en/irovedout/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 000000000..483558a60
Binary files /dev/null and b/src/en/irovedout/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/src/en/irovedout/res/web_hi_res_512.png b/src/en/irovedout/res/web_hi_res_512.png
new file mode 100644
index 000000000..944436dcf
Binary files /dev/null and b/src/en/irovedout/res/web_hi_res_512.png differ
diff --git a/src/en/irovedout/src/eu/kanade/tachiyomi/extension/en/irovedout/IRovedOut.kt b/src/en/irovedout/src/eu/kanade/tachiyomi/extension/en/irovedout/IRovedOut.kt
new file mode 100644
index 000000000..aee0b3911
--- /dev/null
+++ b/src/en/irovedout/src/eu/kanade/tachiyomi/extension/en/irovedout/IRovedOut.kt
@@ -0,0 +1,122 @@
+package eu.kanade.tachiyomi.extension.en.irovedout
+
+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.HttpSource
+import eu.kanade.tachiyomi.util.asJsoup
+import okhttp3.Request
+import okhttp3.Response
+import rx.Observable
+import java.lang.Exception
+import java.text.SimpleDateFormat
+import java.util.Locale
+
+class IRovedOut : HttpSource() {
+
+ override val name = "I Roved Out"
+ override val baseUrl = "https://irovedout.com"
+ override val lang = "en"
+ override val supportsLatest = false
+ private val archiveUrl = "$baseUrl/archive"
+ private val thumbnailUrl = "https://i.ibb.co/2g7Htwq/irovedout.png"
+ private val seriesTitle = "I Roved Out in Search of Truth and Love"
+ private val authorName = "Alexis Flower"
+ private val seriesGenre = "Fantasy"
+ private val seriesDescription = """
+ I ROVED OUT IN SEARCH OF TRUTH AND LOVE is written & illustrated by Alexis Flower.
+ It updates in chunks anywhere between 3 and 30 pages long at least once a month.
+ """.trimIndent()
+ private val dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale.US)
+ private val titleRegex = Regex("Book (?\\d+): (?.+)")
+
+ override fun chapterListRequest(manga: SManga): Request = throw Exception("Not used")
+
+ override fun chapterListParse(response: Response): List = throw Exception("Not used")
+
+ override fun fetchChapterList(manga: SManga): Observable> {
+ val mainPage = client.newCall(GET(baseUrl, headers)).execute().asJsoup()
+ val books = mainPage.select("#menu-menu > li > a[href^=$archiveUrl]")
+
+ var chapterCounter = 1F
+ val chaptersByBook = books.mapIndexed { bookIndex, book ->
+ val bookNumber = bookIndex + 1
+ val bookUrl = book.attr("href")
+ val bookPage = client.newCall(GET(bookUrl, headers)).execute().asJsoup()
+ val chapters = bookPage.select(".comic-archive-chapter-wrap")
+ chapters.map {
+ val chapterWrap = it.selectFirst(".comic-archive-chapter-wrap")
+ SChapter.create().apply {
+ name = "Book $bookNumber: ${chapterWrap.selectFirst(".comic-archive-chapter").text()}"
+ url = chapterWrap.selectFirst(".comic-archive-title > a").attr("href")
+ date_upload = dateFormat.parse(chapterWrap.select(".comic-archive-date").last().text())?.time ?: 0L
+ chapter_number = chapterCounter++
+ }
+ }
+ }
+ return Observable.just(chaptersByBook.flatten().reversed())
+ }
+
+ override fun fetchImageUrl(page: Page): Observable {
+ val comicPage = client.newCall(GET(page.url, headers)).execute().asJsoup()
+ val imageUrl = comicPage.selectFirst("#comic > a > img").attr("src")
+ return Observable.just(imageUrl)
+ }
+
+ override fun imageUrlParse(response: Response): String = throw Exception("Not used")
+
+ override fun latestUpdatesParse(response: Response): MangasPage = throw Exception("Not used")
+
+ override fun latestUpdatesRequest(page: Int): Request = throw Exception("Not used")
+
+ override fun fetchMangaDetails(manga: SManga): Observable {
+ return Observable.just(manga)
+ }
+
+ override fun mangaDetailsParse(response: Response): SManga = throw Exception("Not used")
+
+ override fun fetchPageList(chapter: SChapter): Observable> {
+ val match = titleRegex.matchEntire(chapter.name) ?: return Observable.just(listOf())
+ val bookNumber = match.groups["bookNumber"]!!.value.toInt()
+ val title = match.groups["chapterTitle"]!!.value
+ val bookPage = client.newCall(GET(archiveUrl + if (bookNumber != 1) "-book-$bookNumber" else "", headers)).execute().asJsoup()
+ val chapterWrap = bookPage.select(".comic-archive-chapter-wrap").find { it.selectFirst(".comic-archive-chapter").text() == title }
+ val pageUrls = chapterWrap?.select(".comic-archive-list-wrap .comic-archive-title > a")?.map { it.attr("href") } ?: return Observable.just(listOf())
+ val pages = pageUrls.mapIndexed { pageIndex, pageUrl ->
+ Page(pageIndex, pageUrl)
+ }
+ return Observable.just(pages)
+ }
+
+ override fun pageListRequest(chapter: SChapter): Request = throw Exception("Not used")
+
+ override fun pageListParse(response: Response): List = throw Exception("Not used")
+
+ override fun fetchPopularManga(page: Int): Observable {
+ val manga = SManga.create().apply {
+ url = ""
+ thumbnail_url = thumbnailUrl
+ title = seriesTitle
+ author = authorName
+ artist = authorName
+ description = seriesDescription
+ genre = seriesGenre
+ status = SManga.ONGOING
+ initialized = true
+ }
+ return Observable.just(MangasPage(listOf(manga), false))
+ }
+
+ override fun popularMangaParse(response: Response): MangasPage = throw Exception("Not used")
+
+ override fun popularMangaRequest(page: Int): Request = throw Exception("Not used")
+
+ override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable = throw Exception("Not used")
+
+ override fun searchMangaParse(response: Response): MangasPage = throw Exception("Not used")
+
+ override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = throw Exception("Not used")
+}
diff --git a/src/en/zeroscans/src/eu/kanade/tachiyomi/extension/en/zeroscans/ZeroScansDto.kt b/src/en/zeroscans/src/eu/kanade/tachiyomi/extension/en/zeroscans/ZeroScansDto.kt
index e2914f1e5..f11a6e807 100644
--- a/src/en/zeroscans/src/eu/kanade/tachiyomi/extension/en/zeroscans/ZeroScansDto.kt
+++ b/src/en/zeroscans/src/eu/kanade/tachiyomi/extension/en/zeroscans/ZeroScansDto.kt
@@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.extension.en.zeroscans
-import eu.kanade.tachiyomi.source.model.Page
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement