Readallcomics (#16938)

* ReadAllComics

* ReadAllComics multisrc

* archived categories
This commit is contained in:
AwkwardPeak7 2023-06-30 19:30:44 +05:00 committed by GitHub
parent 672894acfe
commit 67c01b56aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 270 additions and 0 deletions

View File

@ -0,0 +1,11 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="ReadAllComicsGenerator" type="JetRunConfigurationType" nameIsGenerated="true">
<module name="tachiyomi-extensions.multisrc.main" />
<option name="MAIN_CLASS_NAME" value="eu.kanade.tachiyomi.multisrc.readallcomics.ReadAllComicsGenerator" />
<method v="2">
<option name="Make" enabled="true" />
<option name="Gradle.BeforeRunTask" enabled="true" tasks="ktFormat" externalProjectPath="$PROJECT_DIR$/multisrc" vmOptions="" scriptParameters="-Ptheme=readallcomics" />
<option name="Gradle.BeforeRunTask" enabled="true" tasks="ktLint" externalProjectPath="$PROJECT_DIR$/multisrc" vmOptions="" scriptParameters="-Ptheme=readallcomics" />
</method>
</configuration>
</component>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

View File

@ -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\-:]*)""")
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

View File

@ -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)"
}

View File

@ -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<MangasPage> {
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<SManga>()
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<Page> {
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")
}

View File

@ -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<String>) {
ReadAllComicsGenerator().createAll()
}
}
}