diff --git a/.run/ReadAllComicsGenerator.run.xml b/.run/ReadAllComicsGenerator.run.xml
new file mode 100644
index 0000000000..f37bf1f8fd
--- /dev/null
+++ b/.run/ReadAllComicsGenerator.run.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/multisrc/overrides/readallcomics/default/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/readallcomics/default/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000000..fd351bd91d
Binary files /dev/null and b/multisrc/overrides/readallcomics/default/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/readallcomics/default/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/readallcomics/default/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000000..510e4c8278
Binary files /dev/null and b/multisrc/overrides/readallcomics/default/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/readallcomics/default/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/readallcomics/default/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000000..68107c6496
Binary files /dev/null and b/multisrc/overrides/readallcomics/default/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/readallcomics/default/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/readallcomics/default/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..db82daebe4
Binary files /dev/null and b/multisrc/overrides/readallcomics/default/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/readallcomics/default/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/readallcomics/default/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..aa394ccc64
Binary files /dev/null and b/multisrc/overrides/readallcomics/default/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/readallcomics/default/res/web_hi_res_512.png b/multisrc/overrides/readallcomics/default/res/web_hi_res_512.png
new file mode 100644
index 0000000000..0852678705
Binary files /dev/null and b/multisrc/overrides/readallcomics/default/res/web_hi_res_512.png differ
diff --git a/multisrc/overrides/readallcomics/readallcomicscom/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/readallcomics/readallcomicscom/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000000..fd351bd91d
Binary files /dev/null and b/multisrc/overrides/readallcomics/readallcomicscom/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/readallcomics/readallcomicscom/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/readallcomics/readallcomicscom/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000000..510e4c8278
Binary files /dev/null and b/multisrc/overrides/readallcomics/readallcomicscom/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/readallcomics/readallcomicscom/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/readallcomics/readallcomicscom/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000000..68107c6496
Binary files /dev/null and b/multisrc/overrides/readallcomics/readallcomicscom/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/readallcomics/readallcomicscom/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/readallcomics/readallcomicscom/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..db82daebe4
Binary files /dev/null and b/multisrc/overrides/readallcomics/readallcomicscom/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/readallcomics/readallcomicscom/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/readallcomics/readallcomicscom/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..aa394ccc64
Binary files /dev/null and b/multisrc/overrides/readallcomics/readallcomicscom/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/readallcomics/readallcomicscom/res/web_hi_res_512.png b/multisrc/overrides/readallcomics/readallcomicscom/res/web_hi_res_512.png
new file mode 100644
index 0000000000..0852678705
Binary files /dev/null and b/multisrc/overrides/readallcomics/readallcomicscom/res/web_hi_res_512.png differ
diff --git a/multisrc/overrides/readallcomics/readallcomicscom/src/ReadAllComicsCom.kt b/multisrc/overrides/readallcomics/readallcomicscom/src/ReadAllComicsCom.kt
new file mode 100644
index 0000000000..9819226c4b
--- /dev/null
+++ b/multisrc/overrides/readallcomics/readallcomicscom/src/ReadAllComicsCom.kt
@@ -0,0 +1,23 @@
+package eu.kanade.tachiyomi.extension.en.readallcomicscom
+
+import eu.kanade.tachiyomi.multisrc.readallcomics.ReadAllComics
+import eu.kanade.tachiyomi.source.model.SManga
+import org.jsoup.nodes.Element
+
+class ReadAllComicsCom : ReadAllComics("ReadAllComics", "https://readallcomics.com", "en") {
+
+ override fun nullablePopularManga(element: Element): SManga? {
+ return super.nullablePopularManga(element)?.apply {
+ title = title.let {
+ titleRegex.find(it)?.value?.trim()
+ ?.removeSuffix("v")?.trim()
+ ?.substringBeforeLast("vol")
+ ?: it
+ }
+ }
+ }
+
+ companion object {
+ private val titleRegex = Regex("""^([a-zA-Z_.\s\-–:]*)""")
+ }
+}
diff --git a/multisrc/overrides/readallcomics/readallmanga/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/readallcomics/readallmanga/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000000..d45a3817ec
Binary files /dev/null and b/multisrc/overrides/readallcomics/readallmanga/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/readallcomics/readallmanga/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/readallcomics/readallmanga/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000000..17c4a0a3f1
Binary files /dev/null and b/multisrc/overrides/readallcomics/readallmanga/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/readallcomics/readallmanga/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/readallcomics/readallmanga/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000000..16b08944a6
Binary files /dev/null and b/multisrc/overrides/readallcomics/readallmanga/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/readallcomics/readallmanga/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/readallcomics/readallmanga/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..7e2c0ae34b
Binary files /dev/null and b/multisrc/overrides/readallcomics/readallmanga/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/readallcomics/readallmanga/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/readallcomics/readallmanga/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000000..274fc4f449
Binary files /dev/null and b/multisrc/overrides/readallcomics/readallmanga/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/readallcomics/readallmanga/res/web_hi_res_512.png b/multisrc/overrides/readallcomics/readallmanga/res/web_hi_res_512.png
new file mode 100644
index 0000000000..c4320c35fb
Binary files /dev/null and b/multisrc/overrides/readallcomics/readallmanga/res/web_hi_res_512.png differ
diff --git a/multisrc/overrides/readallcomics/readallmanga/src/ReadAllManga.kt b/multisrc/overrides/readallcomics/readallmanga/src/ReadAllManga.kt
new file mode 100644
index 0000000000..aa0f7598ca
--- /dev/null
+++ b/multisrc/overrides/readallcomics/readallmanga/src/ReadAllManga.kt
@@ -0,0 +1,23 @@
+package eu.kanade.tachiyomi.extension.en.readallmanga
+
+import eu.kanade.tachiyomi.multisrc.readallcomics.ReadAllComics
+import eu.kanade.tachiyomi.source.model.SManga
+import org.jsoup.nodes.Document
+
+class ReadAllManga : ReadAllComics("ReadAllManga", "https://readallmanga.com", "en") {
+
+ override fun searchType() = "manga"
+
+ override fun popularMangaTitleSelector() = "div > center"
+
+ override fun mangaDetailsParse(document: Document): SManga {
+ return super.mangaDetailsParse(document).apply {
+ genre = document.select(mangaDetailsGenreSelector()).text()
+ .split("–").joinToString { it.trim() }
+ }
+ }
+
+ override fun mangaDetailsDescriptionSelector() = ".b > span"
+ override fun mangaDetailsGenreSelector() = ".b > p > strong:nth-child(8)"
+ override fun mangaDetailsAuthorSelector() = ".b > p > strong:nth-child(5)"
+}
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/readallcomics/ReadAllComics.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/readallcomics/ReadAllComics.kt
new file mode 100644
index 0000000000..babb5f1d62
--- /dev/null
+++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/readallcomics/ReadAllComics.kt
@@ -0,0 +1,188 @@
+package eu.kanade.tachiyomi.multisrc.readallcomics
+
+import eu.kanade.tachiyomi.network.GET
+import eu.kanade.tachiyomi.network.asObservableSuccess
+import eu.kanade.tachiyomi.network.interceptor.rateLimit
+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.HttpUrl.Companion.toHttpUrlOrNull
+import okhttp3.Interceptor
+import okhttp3.Response
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Document
+import org.jsoup.nodes.Element
+import org.jsoup.select.Elements
+import rx.Observable
+
+abstract class ReadAllComics(
+ override val name: String,
+ override val baseUrl: String,
+ override val lang: String,
+) : ParsedHttpSource() {
+
+ override val supportsLatest = false
+
+ private lateinit var searchPageElements: Elements
+
+ override val client = network.cloudflareClient.newBuilder()
+ .addInterceptor(::archivedCategoryInterceptor)
+ .rateLimit(2)
+ .build()
+
+ protected open fun archivedCategoryInterceptor(chain: Interceptor.Chain): Response {
+ val request = chain.request()
+ val response = chain.proceed(request)
+
+ val document = Jsoup.parse(
+ response.peekBody(Long.MAX_VALUE).string(),
+ request.url.toString(),
+ )
+
+ val newUrl = document.selectFirst(archivedCategorySelector())
+ ?.attr("href")?.toHttpUrlOrNull()
+ ?: return response
+
+ if (newUrl.pathSegments.contains("category")) {
+ response.close()
+
+ return chain.proceed(
+ request.newBuilder()
+ .url(newUrl)
+ .build(),
+ )
+ }
+
+ return response
+ }
+
+ protected open fun archivedCategorySelector() = ".description-archive > p > span > a"
+
+ override fun popularMangaRequest(page: Int) =
+ GET("$baseUrl${if (page > 1)"/page/$page/" else ""}", headers)
+
+ override fun popularMangaParse(response: Response): MangasPage {
+ val document = response.asJsoup()
+
+ val mangas = document.select(popularMangaSelector()).mapNotNull {
+ nullablePopularManga(it)
+ }
+
+ val hasNextPage = document.select(popularMangaNextPageSelector()).first() != null
+
+ return MangasPage(mangas, hasNextPage)
+ }
+
+ protected open fun nullablePopularManga(element: Element): SManga? {
+ val manga = SManga.create().apply {
+ val category = element.classNames()
+ .firstOrNull { it.startsWith("category-") }
+ ?.substringAfter("category-")
+ ?: return null
+
+ url = "/category/$category/"
+ title = element.select(popularMangaTitleSelector()).text()
+ thumbnail_url = element.select(popularMangaThumbnailSelector()).attr("abs:src")
+ }
+
+ return manga
+ }
+
+ override fun popularMangaSelector() = "#post-area > div"
+ override fun popularMangaNextPageSelector() = "div.pagenavi > a.next"
+ protected open fun popularMangaTitleSelector() = "h2"
+ protected open fun popularMangaThumbnailSelector() = "img"
+
+ override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable {
+ return if (page == 1) {
+ client.newCall(searchMangaRequest(page, query, filters))
+ .asObservableSuccess()
+ .map { searchMangaParse(it) }
+ } else {
+ Observable.just(searchPageParse(page))
+ }
+ }
+
+ override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
+ GET("$baseUrl/?story=${query.trim()}&s=&type=${searchType()}", headers)
+
+ protected open fun searchType() = "comic"
+
+ override fun searchMangaParse(response: Response): MangasPage {
+ searchPageElements = response.asJsoup().select(searchMangaSelector())
+
+ return searchPageParse(1)
+ }
+
+ private fun searchPageParse(page: Int): MangasPage {
+ val mangas = mutableListOf()
+ val endRange = ((page * 24) - 1).let { if (it <= searchPageElements.lastIndex) it else searchPageElements.lastIndex }
+
+ for (i in (((page - 1) * 24)..endRange)) {
+ mangas.add(
+ searchMangaFromElement(searchPageElements[i]),
+ )
+ }
+
+ return MangasPage(mangas, endRange < searchPageElements.lastIndex)
+ }
+
+ override fun searchMangaFromElement(element: Element) = SManga.create().apply {
+ setUrlWithoutDomain(element.attr("href"))
+ title = element.text().trim()
+ thumbnail_url = searchCover
+ }
+
+ override fun searchMangaSelector() = ".categories a"
+ override fun searchMangaNextPageSelector() = null
+
+ override fun mangaDetailsParse(document: Document) = SManga.create().apply {
+ title = document.select(mangaDetailsTitleSelector()).text().trim()
+ genre = document.select(mangaDetailsGenreSelector()).joinToString { it.text().trim() }
+ author = document.select(mangaDetailsAuthorSelector()).last()?.text()?.trim()
+ description = document.select(mangaDetailsDescriptionSelector()).text().trim()
+ thumbnail_url = document.select(mangaDetailsThumbnailSelector()).attr("abs:src")
+ }
+
+ protected open fun mangaDetailsTitleSelector() = "h1"
+ protected open fun mangaDetailsGenreSelector() = "p strong"
+ protected open fun mangaDetailsAuthorSelector() = "p > strong"
+ protected open fun mangaDetailsDescriptionSelector() = ".b > strong"
+ protected open fun mangaDetailsThumbnailSelector() = "p img"
+
+ override fun chapterListSelector() = ".list-story a"
+
+ override fun chapterFromElement(element: Element) = SChapter.create().apply {
+ setUrlWithoutDomain(element.attr("href"))
+ name = element.attr("title")
+ }
+
+ override fun pageListParse(document: Document): List {
+ return document.select(pageListSelector()).mapIndexed { idx, element ->
+ Page(idx, "", element.attr("abs:src"))
+ }
+ }
+
+ protected open fun pageListSelector() = "body > div img"
+
+ companion object {
+ private const val searchCover = "https://fakeimg.pl/200x300/?text=No%20Cover%0AOn%20Search&font_size=62"
+ }
+
+ override fun imageUrlParse(document: Document) =
+ throw UnsupportedOperationException("Not Implemented")
+ override fun latestUpdatesRequest(page: Int) =
+ throw UnsupportedOperationException("Not Implemented")
+ override fun latestUpdatesFromElement(element: Element) =
+ throw UnsupportedOperationException("Not Implemented")
+ override fun latestUpdatesSelector() =
+ throw UnsupportedOperationException("Not Implemented")
+ override fun latestUpdatesNextPageSelector() =
+ throw UnsupportedOperationException("Not Implemented")
+ override fun popularMangaFromElement(element: Element) =
+ throw UnsupportedOperationException("Not Implemented")
+}
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/readallcomics/ReadAllComicsGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/readallcomics/ReadAllComicsGenerator.kt
new file mode 100644
index 0000000000..d676412ca9
--- /dev/null
+++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/readallcomics/ReadAllComicsGenerator.kt
@@ -0,0 +1,25 @@
+package eu.kanade.tachiyomi.multisrc.readallcomics
+
+import generator.ThemeSourceData.SingleLang
+import generator.ThemeSourceGenerator
+
+class ReadAllComicsGenerator : ThemeSourceGenerator {
+
+ override val themePkg = "readallcomics"
+
+ override val themeClass = "ReadAllComics"
+
+ override val baseVersionCode: Int = 1
+
+ override val sources = listOf(
+ SingleLang("ReadAllComics", "https://readallcomics.com", "en", className = "ReadAllComicsCom"),
+ SingleLang("ReadAllManga", "https://readallmanga.com", "en"),
+ )
+
+ companion object {
+ @JvmStatic
+ fun main(args: Array) {
+ ReadAllComicsGenerator().createAll()
+ }
+ }
+}