Initial commit

This commit is contained in:
FourTOne5
2024-01-09 04:12:39 +06:00
commit 600c345dfe
8593 changed files with 150590 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 KiB

View File

@@ -0,0 +1,8 @@
package eu.kanade.tachiyomi.extension.id.ainzscansid
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
class AinzScansID : MangaThemesia("Ainz Scans ID", "https://ainzscans.site", "id", "/series") {
override val hasProjectPage = true
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

View File

@@ -0,0 +1,21 @@
package eu.kanade.tachiyomi.extension.es.aiyumanga
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
class AiYuManga : MangaThemesia(
"AiYuManga",
"https://aiyumanhua.com",
"es",
dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale("es")),
) {
// Site moved from ZeistManga to MangaThemesia
override val versionId = 3
override val client = super.client.newBuilder()
.rateLimit(2, 1, TimeUnit.SECONDS)
.build()
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

View File

@@ -0,0 +1,17 @@
package eu.kanade.tachiyomi.extension.id.alceascan
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import okhttp3.OkHttpClient
class Alceascan : MangaThemesia("Alceascan", "https://alceascan.my.id", "id") {
// Website theme changed from zManga to WPMangaThemesia.
override val versionId = 2
override val client: OkHttpClient = super.client.newBuilder()
.rateLimit(20, 4)
.build()
override val hasProjectPage = true
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

View File

@@ -0,0 +1,16 @@
package eu.kanade.tachiyomi.extension.en.animatedglitchedcomics
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import okhttp3.OkHttpClient
class AnimatedGlitchedComics : MangaThemesia(
"Animated Glitched Comics",
"https://agscomics.com",
"en",
mangaUrlDirectory = "/series",
) {
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.rateLimit(1)
.build()
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

View File

@@ -0,0 +1,5 @@
package eu.kanade.tachiyomi.extension.en.animatedglitchedscans
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
class AnimatedGlitchedScans : MangaThemesia("Animated Glitched Scans", "https://anigliscans.xyz", "en", mangaUrlDirectory = "/series")

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@@ -0,0 +1,30 @@
package eu.kanade.tachiyomi.extension.ar.areamanga
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import eu.kanade.tachiyomi.source.model.SManga
import java.text.SimpleDateFormat
import java.util.Locale
class AreaManga : MangaThemesia(
"أريا مانجا",
"https://www.areascans.net",
"ar",
dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale("ar")),
) {
override val seriesArtistSelector =
".tsinfo .imptdt:contains(الرسام) i, ${super.seriesArtistSelector}"
override val seriesAuthorSelector =
".tsinfo .imptdt:contains(المؤلف) i, ${super.seriesAuthorSelector}"
override val seriesStatusSelector =
".tsinfo .imptdt:contains(الحالة) i, ${super.seriesStatusSelector}"
override val seriesTypeSelector =
".tsinfo .imptdt:contains(النوع) i, ${super.seriesTypeSelector}"
override fun String?.parseStatus() = when {
this == null -> SManga.UNKNOWN
this.contains("مستمر", ignoreCase = true) -> SManga.ONGOING
this.contains("مكتمل", ignoreCase = true) -> SManga.COMPLETED
this.contains("متوقف", ignoreCase = true) -> SManga.ON_HIATUS
else -> SManga.UNKNOWN
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.arenascans
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
class ArenaScans : MangaThemesia("Arena Scans", "https://arenascans.net", "en") {
override val pageSelector = "div#readerarea img[data-src]"
}

View File

@@ -0,0 +1,22 @@
package eu.kanade.tachiyomi.extension.pt.arkhamscan
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import okhttp3.OkHttpClient
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
class ArkhamScan : MangaThemesia(
"Arkham Scan",
"https://arkhamscan.com",
"pt-BR",
dateFormat = SimpleDateFormat("MMMMM dd, yyyy", Locale("pt", "BR")),
) {
override val client: OkHttpClient = super.client.newBuilder()
.rateLimit(1, 2, TimeUnit.SECONDS)
.build()
override val altNamePrefix = "Nomes alternativos: "
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

View File

@@ -0,0 +1,13 @@
package eu.kanade.tachiyomi.extension.en.arvenscans
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import okhttp3.OkHttpClient
import java.util.concurrent.TimeUnit
class ArvenScans : MangaThemesia("Arven Scans", "https://arvenscans.com", "en", "/series") {
override val client: OkHttpClient = super.client.newBuilder()
.rateLimit(20, 5, TimeUnit.SECONDS)
.build()
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

View File

@@ -0,0 +1,324 @@
package eu.kanade.tachiyomi.extension.all.asurascans
import android.app.Application
import android.content.SharedPreferences
import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreferenceCompat
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
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 kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
class AsuraScansEn : MangaThemesia(
"Asura Scans",
"https://asuratoon.com",
"en",
dateFormat = SimpleDateFormat("MMM d, yyyy", Locale.US),
) {
private val preferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
override val baseUrl by lazy {
preferences.baseUrlHost.let { "https://$it" }
}
override val client: OkHttpClient = super.client.newBuilder()
.addInterceptor(::urlChangeInterceptor)
.addInterceptor(::domainChangeIntercept)
.rateLimit(1, 3, TimeUnit.SECONDS)
.build()
override val seriesDescriptionSelector = "div.desc p, div.entry-content p, div[itemprop=description]:not(:has(p))"
override val seriesArtistSelector = ".fmed b:contains(artist)+span, .infox span:contains(artist)"
override val seriesAuthorSelector = ".fmed b:contains(author)+span, .infox span:contains(author)"
override val pageSelector = "div.rdminimal > img, div.rdminimal > p > img, div.rdminimal > a > img, div.rdminimal > p > a > img, " +
"div.rdminimal > noscript > img, div.rdminimal > p > noscript > img, div.rdminimal > a > noscript > img, div.rdminimal > p > a > noscript > img"
// Permanent Url for Manga/Chapter End
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
return super.fetchPopularManga(page).tempUrlToPermIfNeeded()
}
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> {
return super.fetchLatestUpdates(page).tempUrlToPermIfNeeded()
}
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
return super.fetchSearchManga(page, query, filters).tempUrlToPermIfNeeded()
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val request = super.searchMangaRequest(page, query, filters)
if (query.isBlank()) return request
val url = request.url.newBuilder()
.addPathSegment("page/$page/")
.removeAllQueryParameters("page")
.removeAllQueryParameters("title")
.addQueryParameter("s", query)
.build()
return request.newBuilder()
.url(url)
.build()
}
// Temp Url for manga/chapter
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
val newManga = manga.titleToUrlFrag()
return super.fetchChapterList(newManga)
}
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
val newManga = manga.titleToUrlFrag()
return super.fetchMangaDetails(newManga)
}
override fun getMangaUrl(manga: SManga): String {
val dbSlug = manga.url
.substringBefore("#")
.removeSuffix("/")
.substringAfterLast("/")
val storedSlug = preferences.slugMap[dbSlug] ?: dbSlug
return "$baseUrl$mangaUrlDirectory/$storedSlug/"
}
// Skip scriptPages
override fun pageListParse(document: Document): List<Page> {
return document.select(pageSelector)
.filterNot { it.attr("src").isNullOrEmpty() }
.mapIndexed { i, img -> Page(i, document.location(), img.attr("abs:src")) }
}
override fun Element.imgAttr(): String = when {
hasAttr("data-lazy-src") -> attr("abs:data-lazy-src")
hasAttr("data-src") -> attr("abs:data-src")
hasAttr("data-cfsrc") -> attr("abs:data-cfsrc")
else -> attr("abs:src")
}
private fun Observable<MangasPage>.tempUrlToPermIfNeeded(): Observable<MangasPage> {
return this.map { mangasPage ->
MangasPage(
mangasPage.mangas.map { it.tempUrlToPermIfNeeded() },
mangasPage.hasNextPage,
)
}
}
private fun SManga.tempUrlToPermIfNeeded(): SManga {
if (!preferences.permaUrlPref) return this
val slugMap = preferences.slugMap
val sMangaTitleFirstWord = this.title.split(" ")[0]
if (!this.url.contains("/$sMangaTitleFirstWord", ignoreCase = true)) {
val currentSlug = this.url
.removeSuffix("/")
.substringAfterLast("/")
val permaSlug = currentSlug.replaceFirst(TEMP_TO_PERM_REGEX, "")
slugMap[permaSlug] = currentSlug
this.url = "$mangaUrlDirectory/$permaSlug/"
}
preferences.slugMap = slugMap
return this
}
private fun SManga.titleToUrlFrag(): SManga {
return try {
this.apply {
url = "$url#${title.toSearchQuery()}"
}
} catch (e: UninitializedPropertyAccessException) {
// when called from deep link, title is not present
this
}
}
private fun urlChangeInterceptor(chain: Interceptor.Chain): Response {
val request = chain.request()
val frag = request.url.fragment
if (frag.isNullOrEmpty()) {
return chain.proceed(request)
}
val dbSlug = request.url.toString()
.substringBefore("#")
.removeSuffix("/")
.substringAfterLast("/")
val slugMap = preferences.slugMap
val storedSlug = slugMap[dbSlug] ?: dbSlug
val response = chain.proceed(
request.newBuilder()
.url("$baseUrl$mangaUrlDirectory/$storedSlug/")
.build(),
)
if (!response.isSuccessful && response.code == 404) {
response.close()
val newSlug = getNewSlug(storedSlug, frag)
?: throw IOException("Migrate from Asura to Asura")
slugMap[dbSlug] = newSlug
preferences.slugMap = slugMap
return chain.proceed(
request.newBuilder()
.url("$baseUrl$mangaUrlDirectory/$newSlug/")
.build(),
)
}
return response
}
private fun getNewSlug(existingSlug: String, frag: String): String? {
val permaSlug = existingSlug
.replaceFirst(TEMP_TO_PERM_REGEX, "")
val search = frag.substringBefore("#")
val mangas = client.newCall(searchMangaRequest(1, search, FilterList()))
.execute()
.use {
searchMangaParse(it)
}
return mangas.mangas.firstOrNull { newManga ->
newManga.url.contains(permaSlug, true)
}
?.url
?.removeSuffix("/")
?.substringAfterLast("/")
}
private fun String.toSearchQuery(): String {
return this.trim()
.lowercase()
.replace(titleSpecialCharactersRegex, "+")
.replace(trailingPlusRegex, "")
}
private var lastDomain = ""
private fun domainChangeIntercept(chain: Interceptor.Chain): Response {
val request = chain.request()
if (request.url.host !in listOf(preferences.baseUrlHost, lastDomain)) {
return chain.proceed(request)
}
if (lastDomain.isNotEmpty()) {
val newUrl = request.url.newBuilder()
.host(preferences.baseUrlHost)
.build()
return chain.proceed(
request.newBuilder()
.url(newUrl)
.build(),
)
}
val response = chain.proceed(request)
if (request.url.host == response.request.url.host) return response
response.close()
preferences.baseUrlHost = response.request.url.host
lastDomain = request.url.host
val newUrl = request.url.newBuilder()
.host(response.request.url.host)
.build()
return chain.proceed(
request.newBuilder()
.url(newUrl)
.build(),
)
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
SwitchPreferenceCompat(screen.context).apply {
key = PREF_PERM_MANGA_URL_KEY_PREFIX + lang
title = PREF_PERM_MANGA_URL_TITLE
summary = PREF_PERM_MANGA_URL_SUMMARY
setDefaultValue(true)
}.also(screen::addPreference)
super.setupPreferenceScreen(screen)
}
private val SharedPreferences.permaUrlPref
get() = getBoolean(PREF_PERM_MANGA_URL_KEY_PREFIX + lang, true)
private var SharedPreferences.slugMap: MutableMap<String, String>
get() {
val serialized = getString(PREF_URL_MAP, null) ?: return mutableMapOf()
return try {
json.decodeFromString(serialized)
} catch (e: Exception) {
mutableMapOf()
}
}
set(slugMap) {
val serialized = json.encodeToString(slugMap)
edit().putString(PREF_URL_MAP, serialized).commit()
}
private var SharedPreferences.baseUrlHost
get() = getString(BASE_URL_PREF, defaultBaseUrlHost) ?: defaultBaseUrlHost
set(newHost) {
edit().putString(BASE_URL_PREF, newHost).commit()
}
companion object {
private const val PREF_PERM_MANGA_URL_KEY_PREFIX = "pref_permanent_manga_url_2_"
private const val PREF_PERM_MANGA_URL_TITLE = "Permanent Manga URL"
private const val PREF_PERM_MANGA_URL_SUMMARY = "Turns all manga urls into permanent ones."
private const val PREF_URL_MAP = "pref_url_map"
private const val BASE_URL_PREF = "pref_base_url_host"
private const val defaultBaseUrlHost = "asuratoon.com"
private val TEMP_TO_PERM_REGEX = Regex("""^\d+-""")
private val titleSpecialCharactersRegex = Regex("""[^a-z0-9]+""")
private val trailingPlusRegex = Regex("""\++$""")
}
}

View File

@@ -0,0 +1,10 @@
package eu.kanade.tachiyomi.extension.all.asurascans
import eu.kanade.tachiyomi.source.SourceFactory
class AsuraScansFactory : SourceFactory {
override fun createSources() = listOf(
AsuraScansEn(),
AsuraScansTr(),
)
}

View File

@@ -0,0 +1,66 @@
package eu.kanade.tachiyomi.extension.all.asurascans
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SManga
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import okhttp3.OkHttpClient
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
class AsuraScansTr : MangaThemesia(
"Asura Scans",
"https://armoniscans.com",
"tr",
dateFormat = SimpleDateFormat("MMM d, yyyy", Locale("tr")),
) {
override val client: OkHttpClient = super.client.newBuilder()
.rateLimit(1, 3, TimeUnit.SECONDS)
.build()
override val seriesArtistSelector = ".fmed b:contains(Çizer)+span"
override val seriesAuthorSelector = ".fmed b:contains(Yazar)+span"
override val seriesStatusSelector = ".imptdt:contains(Durum) i"
override val seriesTypeSelector = ".imptdt:contains(Tür) a"
override val altNamePrefix: String = "Alternatif isim: "
override fun String?.parseStatus(): Int = when {
this == null -> SManga.UNKNOWN
this.contains("Devam Ediyor", ignoreCase = true) -> SManga.ONGOING
this.contains("Tamamlandı", ignoreCase = true) -> SManga.COMPLETED
else -> SManga.UNKNOWN
}
override fun Element.imgAttr(): String = when {
hasAttr("data-lazy-src") -> attr("abs:data-lazy-src")
hasAttr("data-src") -> attr("abs:data-src")
hasAttr("data-cfsrc") -> attr("abs:data-cfsrc")
else -> attr("abs:src")
}
override fun pageListParse(document: Document): List<Page> {
val scriptContent = document.selectFirst("script:containsData(ts_reader)")?.data()
?: return super.pageListParse(document)
val jsonString = scriptContent.substringAfter("ts_reader.run(").substringBefore(");")
val tsReader = json.decodeFromString<TSReader>(jsonString)
val imageUrls = tsReader.sources.firstOrNull()?.images ?: return emptyList()
return imageUrls.mapIndexed { index, imageUrl -> Page(index, document.location(), imageUrl) }
}
@Serializable
data class TSReader(
val sources: List<ReaderImageSource>,
)
@Serializable
data class ReaderImageSource(
val source: String,
val images: List<String>,
)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.fr.bananascan
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import java.text.SimpleDateFormat
import java.util.Locale
class BananaScan : MangaThemesia("Banana-Scan", "https://banana-scan.com", "fr", dateFormat = SimpleDateFormat("MMMM d, yyyy", Locale.FRENCH))

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

View File

@@ -0,0 +1,7 @@
package eu.kanade.tachiyomi.extension.en.batotoscans
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
class BatotoScans : MangaThemesia("Snudae Scans", "https://snudaescans.com", "en") {
override val id = 4418350353197826372L
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

View File

@@ -0,0 +1,31 @@
package eu.kanade.tachiyomi.extension.ar.beastscans
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import eu.kanade.tachiyomi.source.model.SManga
import java.text.SimpleDateFormat
import java.util.Locale
class BeastScans : MangaThemesia(
"Beast Scans",
"https://beastscans.net",
"ar",
dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale("ar")),
) {
override val seriesArtistSelector =
".infox .fmed:contains(الرسام) span, ${super.seriesArtistSelector}"
override val seriesAuthorSelector =
".infox .fmed:contains(المؤلف) span, ${super.seriesAuthorSelector}"
override val seriesStatusSelector =
".tsinfo .imptdt:contains(الحالة) i, ${super.seriesStatusSelector}"
override val seriesTypeSelector =
".tsinfo .imptdt:contains(النوع) i, ${super.seriesTypeSelector}"
override fun String?.parseStatus() = when {
this == null -> SManga.UNKNOWN
listOf("مستمر", "ongoing", "publishing").any { this.contains(it, ignoreCase = true) } -> SManga.ONGOING
listOf("متوقف", "hiatus").any { this.contains(it, ignoreCase = true) } -> SManga.ON_HIATUS
listOf("مكتمل", "completed").any { this.contains(it, ignoreCase = true) } -> SManga.COMPLETED
listOf("dropped", "cancelled").any { this.contains(it, ignoreCase = true) } -> SManga.CANCELLED
else -> SManga.UNKNOWN
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

View File

@@ -0,0 +1,18 @@
package eu.kanade.tachiyomi.extension.es.berserkerscan
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
class BerserkerScan : MangaThemesia(
"Berserker Scan",
"https://ragnascan.com",
"es",
dateFormat = SimpleDateFormat("MMMM d, yyyy", Locale("es")),
) {
override val client = super.client.newBuilder()
.rateLimit(2, 1, TimeUnit.SECONDS)
.build()
}

Some files were not shown because too many files have changed in this diff Show More