Remove domains with no A record (#7481)

This commit is contained in:
Vetle Ledaal 2025-02-03 15:13:25 +01:00 committed by Draff
parent f6b09f2a03
commit b6194e68b3
No known key found for this signature in database
GPG Key ID: E8A89F3211677653
225 changed files with 0 additions and 4166 deletions

View File

@ -1,10 +0,0 @@
ext {
extName = 'Eromanhwa'
extClass = '.Eromanhwa'
themePkg = 'madara'
baseUrl = 'https://eromanhwa.org'
overrideVersionCode = 1
isNsfw = true
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,12 +0,0 @@
package eu.kanade.tachiyomi.extension.all.eromanhwa
import eu.kanade.tachiyomi.multisrc.madara.Madara
class Eromanhwa : Madara(
"Eromanhwa",
"https://eromanhwa.org",
"all",
) {
override val id = 3597355706480775153 // accidently set lang to en...
override val useNewChapterEndpoint = true
}

View File

@ -1,8 +0,0 @@
ext {
extName = 'Frelein Books'
extClass = '.FreleinBooks'
extVersionCode = 1
isNsfw = false
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

View File

@ -1,271 +0,0 @@
package eu.kanade.tachiyomi.extension.all.freleinbooks
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
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.Request
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
class FreleinBooks() : ParsedHttpSource() {
override val baseUrl = "https://books.frelein.my.id"
override val lang = "all"
override val name = "Frelein Books"
override val supportsLatest = true
override fun headersBuilder() = super.headersBuilder()
.add("Referer", "$baseUrl/")
private val Element.imgSrc: String
get() = attr("data-lazy-src")
.ifEmpty { attr("data-src") }
.ifEmpty { attr("src") }
// Latest
override fun latestUpdatesFromElement(element: Element): SManga {
val manga = SManga.create()
manga.thumbnail_url = element.selectFirst("img")!!.imgSrc
manga.title = element.select(".postTitle").text()
manga.setUrlWithoutDomain(element.select(".postTitle > a").attr("abs:href"))
return manga
}
override fun latestUpdatesNextPageSelector() = ".olderLink"
override fun latestUpdatesRequest(page: Int): Request {
return if (page == 1) {
GET(baseUrl)
} else {
val dateParam = page * 7 * 2
// Calendar set to the current date
val calendar: Calendar = Calendar.getInstance()
// rollback 14 days
calendar.add(Calendar.DAY_OF_YEAR, -dateParam)
val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.US)
// now the date is 14 days back
GET("$baseUrl/search?updated-max=${formatter.format(calendar.time)}T12:38:00%2B07:00&max-results=12&start=12&by-date=false")
}
}
override fun latestUpdatesSelector() = ".blogPosts > article"
// Popular
override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create()
manga.thumbnail_url = element.selectFirst("img")!!.imgSrc
manga.title = element.select("h3").text()
manga.setUrlWithoutDomain(element.select("h3 > a").attr("abs:href"))
return manga
}
override fun popularMangaNextPageSelector(): String? = null
override fun popularMangaRequest(page: Int) = latestUpdatesRequest(page)
override fun popularMangaSelector() = ".itemPopulars article"
// Search
override fun searchMangaFromElement(element: Element) = latestUpdatesFromElement(element)
override fun searchMangaNextPageSelector() = latestUpdatesNextPageSelector()
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val filterList = if (filters.isEmpty()) getFilterList() else filters
val tagFilter = filterList.findInstance<TagFilter>()!!
val groupFilter = filterList.findInstance<GroupFilter>()!!
val magazineFilter = filterList.findInstance<MagazineFilter>()!!
val fashionMagazineFilter = filterList.findInstance<FashionMagazineFilter>()!!
return when {
query.isEmpty() && groupFilter.state != 0 -> GET("$baseUrl/search/label/${groupFilter.toUriPart()}")
query.isEmpty() && magazineFilter.state != 0 -> GET("$baseUrl/search/label/${magazineFilter.toUriPart()}")
query.isEmpty() && fashionMagazineFilter.state != 0 -> GET("$baseUrl/search/label/${fashionMagazineFilter.toUriPart()}")
query.isEmpty() && tagFilter.state.isNotEmpty() -> GET("$baseUrl/search/label/${tagFilter.state}")
query.isNotEmpty() -> GET("$baseUrl/search?q=$query")
else -> latestUpdatesRequest(page)
}
}
override fun searchMangaSelector() = latestUpdatesSelector()
// Details
override fun mangaDetailsParse(document: Document): SManga {
val manga = SManga.create()
manga.title = document.select(".postTitle").text()
manga.description = "Read ${document.select(".postTitle").text()} \n \nNote: If you encounters error when opening the magazine, please press the WebView button then leave a comment on our web so we can update it soon."
manga.genre = document.select(".labelLink > a")
.joinToString(", ") { it.text() }
manga.status = SManga.COMPLETED
return manga
}
override fun chapterFromElement(element: Element): SChapter {
val chapter = SChapter.create()
chapter.setUrlWithoutDomain(element.select("link[rel=\"canonical\"]").attr("href"))
chapter.name = "Gallery"
chapter.date_upload = getDate(element.select("link[rel=\"canonical\"]").attr("href"))
return chapter
}
override fun chapterListSelector() = "html"
// Pages
override fun pageListParse(document: Document): List<Page> {
val pages = mutableListOf<Page>()
document.select("noscript").remove()
document.select(".gallerybox a > img").forEachIndexed { i, it ->
// format new img/b/
if (it.imgSrc.contains("img/b/")) {
if (it.imgSrc.contains("/w768-rw/")) {
val itUrl = it.imgSrc.replace("/w768-rw/", "/s0/")
pages.add(Page(i, itUrl, itUrl))
}
if (it.imgSrc.contains("/w480-rw/")) {
val itUrl = it.imgSrc.replace("/w480-rw/", "/s0/")
pages.add(Page(i, itUrl, itUrl))
}
}
// format new img/b/
else {
if (it.imgSrc.contains("=w768-rw")) {
val itUrl = it.imgSrc.replace("=w768-rw", "")
pages.add(Page(i, itUrl, itUrl))
} else if (it.imgSrc.contains("=w480-rw")) {
val itUrl = it.imgSrc.replace("=w480-rw", "")
pages.add(Page(i, itUrl, itUrl))
} else {
val itUrl = it.imgSrc
pages.add(Page(i, itUrl, itUrl))
}
}
}
return pages
}
override fun imageUrlParse(document: Document): String =
throw UnsupportedOperationException()
// Filters
override fun getFilterList(): FilterList = FilterList(
Filter.Header("NOTE: Only one filter will be applied!"),
Filter.Separator(),
GroupFilter(),
MagazineFilter(),
FashionMagazineFilter(),
TagFilter(),
)
open class UriPartFilter(
displayName: String,
private val valuePair: Array<Pair<String, String>>,
) : Filter.Select<String>(displayName, valuePair.map { it.first }.toTypedArray()) {
fun toUriPart() = valuePair[state].second
}
class MagazineFilter : UriPartFilter(
"Magazine",
arrayOf(
Pair("Any", ""),
Pair("B.L.T.", "B.L.T."),
Pair("BIG ONE GIRLS", "BIG ONE GIRLS"),
Pair("BOMB!", "BOMB!"),
Pair("BRODY", "BRODY"),
Pair("BUBKA", "BUBKA"),
Pair("ENTAME", "ENTAME"),
Pair("EX Taishu", "EX Taishu"),
Pair("FINEBOYS", "FINEBOYS"),
Pair("FLASH", "FLASH"),
Pair("Fine", "Fine"),
Pair("Friday", "Friday"),
Pair("HINA_SATSU", "HINA_SATSU"),
Pair("IDOL AND READ", "IDOL AND READ"),
Pair("Kadokawa Scene 07", "Kadokawa Scene 07"),
Pair("Monthly Basketball", "Monthly Basketball"),
Pair("Monthly Young Magazine", "Monthly Young Magazine"),
Pair("NOGI_SATSU", "NOGI_SATSU"),
Pair("Nylon Japan", "Nylon Japan"),
Pair("Platinum FLASH", "Platinum FLASH"),
Pair("Shonen Magazine", "Shonen Magazine"),
Pair("Shukan Post", "Shukan Post"),
Pair("TOKYO NEWS MOOK", "TOKYO NEWS MOOK"),
Pair("TV LIFE,Tarzan", "TV LIFE,Tarzan"),
Pair("Tokyo Calendar", "Tokyo Calendar"),
Pair("Top Yell NEO", "Top Yell NEO"),
Pair("UTB", "UTB"),
Pair("Weekly Playboy", "Weekly Playboy"),
Pair("Weekly SPA", "Weekly SPA"),
Pair("Weekly SPA!", "Weekly SPA!"),
Pair("Weekly Shonen Champion", "Weekly Shonen Champion"),
Pair("Weekly Shonen Magazine", "Weekly Shonen Magazine"),
Pair("Weekly Shonen Sunday", "Weekly Shonen Sunday"),
Pair("Weekly Shounen Magazine", "Weekly Shounen Magazine"),
Pair("Weekly The Television Plus", "Weekly The Television Plus"),
Pair("Weekly Zero Jump", "Weekly Zero Jump"),
Pair("Yanmaga Web", "Yanmaga Web"),
Pair("Young Animal", "Young Animal"),
Pair("Young Champion", "Young Champion"),
Pair("Young Gangan", "Young Gangan"),
Pair("Young Jump", "Young Jump"),
Pair("Young Magazine", "Young Magazine"),
Pair("blt graph.", "blt graph."),
Pair("mini", "mini"),
),
)
class FashionMagazineFilter : UriPartFilter(
"Fashion Magazine",
arrayOf(
Pair("Any", ""),
Pair("BAILA", "BAILA"),
Pair("Biteki", "Biteki"),
Pair("CLASSY", "CLASSY"),
Pair("CanCam", "CanCam"),
Pair("JJ", "JJ"),
Pair("LARME", "LARME"),
Pair("MARQUEE", "MARQUEE"),
Pair("Maquia", "Maquia"),
Pair("Men's non-no", "Men's non-no"),
Pair("More", "More"),
Pair("Oggi", "Oggi"),
Pair("Ray", "Ray"),
Pair("Seventeen", "Seventeen"),
Pair("Sweet", "Sweet"),
Pair("VOCE", "VOCE"),
Pair("ViVi", "ViVi"),
Pair("With", "With"),
Pair("aR", "aR"),
Pair("anan", "anan"),
Pair("bis", "bis"),
Pair("non-no", "non-no"),
),
)
class GroupFilter : UriPartFilter(
"Group",
arrayOf(
Pair("Any", ""),
Pair("Hinatazaka46", "Hinatazaka46"),
Pair("Nogizaka46", "Nogizaka46"),
Pair("Sakurazaka46", "Sakurazaka46"),
Pair("Keyakizaka46", "Keyakizaka46"),
),
)
class TagFilter : Filter.Text("Tag")
private inline fun <reified T> Iterable<*>.findInstance() = find { it is T } as? T
private fun getDate(str: String): Long {
val regex = "[0-9]{4}\\/[0-9]{2}\\/[0-9]{2}".toRegex()
val match = regex.find(str)
return runCatching { DATE_FORMAT.parse(match!!.value)?.time }.getOrNull() ?: 0L
}
companion object {
private val DATE_FORMAT by lazy {
SimpleDateFormat("yyyy/MM/dd", Locale.US)
}
}
}

View File

@ -1,10 +0,0 @@
ext {
extName = 'Comic Arab'
extClass = '.ComicArab'
themePkg = 'madara'
baseUrl = 'https://comicarab.com'
overrideVersionCode = 0
isNsfw = true
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

View File

@ -1,12 +0,0 @@
package eu.kanade.tachiyomi.extension.ar.comicarab
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class ComicArab : Madara(
"كوميك العرب",
"https://comicarab.com",
"ar",
dateFormat = SimpleDateFormat("dd MMMM، yyyy", Locale("ar")),
)

View File

@ -1,7 +0,0 @@
ext {
extName = 'Manga.ae'
extClass = '.MangaAe'
extVersionCode = 13
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -1,193 +0,0 @@
package eu.kanade.tachiyomi.extension.ar.mangaae
import android.app.Application
import android.widget.Toast
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
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.HttpUrl.Companion.toHttpUrl
import okhttp3.Request
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class MangaAe : ParsedHttpSource(), ConfigurableSource {
override val name = "مانجا العرب"
override val baseUrl by lazy {
when {
System.getenv("CI") == "true" -> MIRROR_PREF_ENTRY_VALUES.joinToString("#, ")
else -> preferences.getString(MIRROR_PREF_KEY, MIRROR_PREF_DEFAULT_VALUE)!!
}
}
private val preferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
override val lang = "ar"
override val supportsLatest = true
override val client = network.cloudflareClient.newBuilder()
.rateLimit(2)
.build()
override fun headersBuilder() = super.headersBuilder()
.set("Referer", "$baseUrl/")
.set("Origin", baseUrl)
// ============================== Popular ===============================
override fun popularMangaRequest(page: Int) = GET("$baseUrl/manga/page:$page", headers)
override fun popularMangaSelector() = "div.mangacontainer"
override fun popularMangaFromElement(element: Element) = SManga.create().apply {
thumbnail_url = element.selectFirst("img")?.run {
attr("data-pagespeed-lazy-src").ifEmpty { attr("src") }
}
element.selectFirst("div.mangacontainer a.manga")!!.run {
title = text()
setUrlWithoutDomain(absUrl("href"))
}
}
override fun popularMangaNextPageSelector() = "div.pagination a:last-child:not(.active)"
// =============================== Latest ===============================
override fun latestUpdatesRequest(page: Int) = GET(baseUrl, headers)
override fun latestUpdatesSelector() = "div.popular-manga-container"
override fun latestUpdatesFromElement(element: Element) = SManga.create().apply {
thumbnail_url = element.selectFirst("img")?.run {
attr("data-pagespeed-lazy-src").ifEmpty { attr("src") }
}
setUrlWithoutDomain(element.selectFirst("a:has(img)")!!.attr("href"))
title = element.selectFirst("a:last-child")!!.text()
}
override fun latestUpdatesNextPageSelector() = null
// =============================== Search ===============================
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = buildString {
append("$baseUrl/manga/search:$query|page:$page")
filters.firstOrNull { it is OrderByFilter }
?.takeUnless { it.state == 0 }
?.also {
val filter = it as OrderByFilter
append("|order:${filter.toUriPart()}")
}
append("|arrange:minus")
}
return GET(url.toHttpUrl(), headers)
}
override fun searchMangaSelector() = popularMangaSelector()
override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element)
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
// =========================== Manga Details ============================
override fun mangaDetailsParse(document: Document) = SManga.create().apply {
val infoElement = document.selectFirst("div.indexcontainer")!!
// Essential info, a NPE may be understandable
with(infoElement) {
title = selectFirst("h1.EnglishName")!!.text().removeSurrounding("(", ")")
author = selectFirst("div.manga-details-author h4")?.text()
artist = author
thumbnail_url = selectFirst("img.manga-cover")?.attr("src")
}
// Additional info
infoElement.selectFirst("div.manga-details-extended")?.run {
status = parseStatus(selectFirst("td h4")?.text().orEmpty())
genre = select("a[href*=tag]").eachText().joinToString()
description = selectFirst("h4[style*=overflow-y]")?.text()
}
}
private fun parseStatus(status: String) = when {
status.contains("مستمرة") -> SManga.ONGOING
status.contains("مكتملة") -> SManga.COMPLETED
else -> SManga.UNKNOWN
}
// ============================== Chapters ==============================
override fun chapterListSelector() = "ul.new-manga-chapters > li a"
override fun chapterFromElement(element: Element) = SChapter.create().apply {
setUrlWithoutDomain(element.attr("href").removeSuffix("/1/") + "/0/allpages")
name = "\u061C" + element.text() // Add unicode ARABIC LETTER MARK to ensure all titles are right to left
}
// =============================== Pages ================================
override fun pageListParse(document: Document): List<Page> {
return document.select("div#showchaptercontainer img").mapIndexed { index, item ->
Page(index, "", item.attr("src"))
}
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
// ============================== Filters ===============================
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
fun toUriPart() = vals[state].second
}
private class OrderByFilter : UriPartFilter(
"الترتيب حسب",
arrayOf(
Pair("اختيار", ""),
Pair("اسم المانجا", "english_name"),
Pair("تاريخ النشر", "release_date"),
Pair("عدد الفصول", "chapter_count"),
Pair("الحالة", "status"),
),
)
override fun getFilterList() = FilterList(OrderByFilter())
// ============================== Settings ==============================
companion object {
private const val RESTART_TACHIYOMI = "أعد تشغيل التطبيق لتمكين الإعدادات الجديدة."
private const val MIRROR_PREF_KEY = "MIRROR"
private const val MIRROR_PREF_TITLE = "تعديل الرابط"
internal val MIRROR_PREF_ENTRY_VALUES = arrayOf(
"https://mangaae.com",
"https://mangaat.com",
"https://mngaar.com",
)
private val MIRROR_PREF_DEFAULT_VALUE = MIRROR_PREF_ENTRY_VALUES[0]
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val mirrorPref = ListPreference(screen.context).apply {
key = MIRROR_PREF_KEY
title = MIRROR_PREF_TITLE
entries = MIRROR_PREF_ENTRY_VALUES
entryValues = MIRROR_PREF_ENTRY_VALUES
setDefaultValue(MIRROR_PREF_DEFAULT_VALUE)
summary = "%s"
setOnPreferenceChangeListener { _, _ ->
Toast.makeText(screen.context, RESTART_TACHIYOMI, Toast.LENGTH_LONG).show()
true
}
}
screen.addPreference(mirrorPref)
}
}

View File

@ -1,9 +0,0 @@
ext {
extName = 'Kuma Scans (Kuma Translation)'
extClass = '.KumaScans'
themePkg = 'mangathemesia'
baseUrl = 'https://kumascans.com'
overrideVersionCode = 1
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

View File

@ -1,14 +0,0 @@
package eu.kanade.tachiyomi.extension.en.kumascans
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import okhttp3.OkHttpClient
class KumaScans : MangaThemesia("Kuma Scans (Kuma Translation)", "https://kumascans.com", "en") {
override val client: OkHttpClient = super.client.newBuilder()
.rateLimit(4)
.build()
override val hasProjectPage = true
}

View File

@ -1,10 +0,0 @@
ext {
extName = 'LuxManga'
extClass = '.LuxManga'
themePkg = 'madara'
baseUrl = 'https://luxmanga.net'
overrideVersionCode = 1
isNsfw = true
}
apply from: "$rootDir/common.gradle"

View File

@ -1,7 +0,0 @@
package eu.kanade.tachiyomi.extension.en.luxmanga
import eu.kanade.tachiyomi.multisrc.madara.Madara
class LuxManga : Madara("LuxManga", "https://luxmanga.net", "en") {
override val useNewChapterEndpoint = false
}

View File

@ -1,10 +0,0 @@
ext {
extName = 'Manga1k'
extClass = '.Manga1k'
themePkg = 'madara'
baseUrl = 'https://manga1k.com'
overrideVersionCode = 0
isNsfw = true
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

View File

@ -1,12 +0,0 @@
package eu.kanade.tachiyomi.extension.en.manga1k
import eu.kanade.tachiyomi.multisrc.madara.Madara
class Manga1k : Madara(
"Manga1k",
"https://manga1k.com",
"en",
) {
override val useLoadMoreRequest = LoadMoreStrategy.Never
override val useNewChapterEndpoint = false
}

View File

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity android:name=".en.mangafun.MangaFunUrlActivity"
android:excludeFromRecents="true"
android:exported="true"
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="mangafun.me"
android:pathPattern="/title/..*" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -1,13 +0,0 @@
ext {
extName = "Manga Fun"
extClass = ".MangaFun"
extVersionCode = 1
isNsfw = true
}
apply from: "$rootDir/common.gradle"
dependencies {
implementation("net.pearx.kasechange:kasechange:1.4.1")
implementation(project(':lib:lzstring'))
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,134 +0,0 @@
package eu.kanade.tachiyomi.extension.en.mangafun
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.buildJsonArray
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.intOrNull
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonNull
import kotlinx.serialization.json.jsonPrimitive
/**
* A somewhat direct port of the decoding parts of
* [compress-json](https://github.com/beenotung/compress-json).
*/
object DecompressJson {
fun decompress(c: JsonArray): JsonElement {
val values = c[0].jsonArray
val key = c[1].jsonPrimitive.content
return decode(values, key)
}
private fun decode(values: JsonArray, key: String): JsonElement {
if (key.isEmpty() || key == "_") {
return JsonPrimitive(null)
}
val id = sToInt(key)
val v = values[id]
try {
v.jsonNull
return v
} catch (_: IllegalArgumentException) {
// v is not null, we continue on.
}
val vNum = v.jsonPrimitive.intOrNull
if (vNum != null) {
return v
}
if (v.jsonPrimitive.isString) {
val content = v.jsonPrimitive.content
if (content.length < 2) {
return v
}
return when (content.substring(0..1)) {
"b|" -> decodeBool(content)
"n|" -> decodeNum(content)
"o|" -> decodeObject(values, content)
"a|" -> decodeArray(values, content)
else -> v
}
}
throw IllegalArgumentException("Unknown data type")
}
private fun decodeObject(values: JsonArray, s: String): JsonObject {
if (s == "o|") {
return JsonObject(emptyMap())
}
val vs = s.split("|")
val keyId = vs[1]
val keys = decode(values, keyId)
val n = vs.size
val keyArray = try {
keys.jsonArray.map { it.jsonPrimitive.content }
} catch (_: IllegalArgumentException) {
// single-key object using existing value as key
listOf(keys.jsonPrimitive.content)
}
return buildJsonObject {
for (i in 2 until n) {
val k = keyArray[i - 2]
val v = decode(values, vs[i])
put(k, v)
}
}
}
private fun decodeArray(values: JsonArray, s: String): JsonArray {
if (s == "a|") {
return JsonArray(emptyList())
}
val vs = s.split("|")
val n = vs.size - 1
return buildJsonArray {
for (i in 0 until n) {
add(decode(values, vs[i + 1]))
}
}
}
private fun decodeBool(s: String): JsonPrimitive {
return when (s) {
"b|T" -> JsonPrimitive(true)
"b|F" -> JsonPrimitive(false)
else -> JsonPrimitive(s.isNotEmpty())
}
}
private fun decodeNum(s: String): JsonPrimitive =
JsonPrimitive(sToInt(s.substringAfter("n|")))
private fun sToInt(s: String): Int {
var acc = 0
var pow = 1
s.reversed().forEach {
acc += stoi[it]!! * pow
pow *= 62
}
return acc
}
private val itos = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
private val stoi = itos.associate {
it to itos.indexOf(it)
}
}

View File

@ -1,296 +0,0 @@
package eu.kanade.tachiyomi.extension.en.mangafun
import android.util.Base64
import android.util.Log
import eu.kanade.tachiyomi.extension.en.mangafun.MangaFunUtils.toSChapter
import eu.kanade.tachiyomi.extension.en.mangafun.MangaFunUtils.toSManga
import eu.kanade.tachiyomi.lib.lzstring.LZString
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.model.Filter
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 kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.Request
import okhttp3.Response
import rx.Observable
import uy.kohesive.injekt.injectLazy
import kotlin.math.min
class MangaFun : HttpSource() {
override val name = "Manga Fun"
override val baseUrl = "https://mangafun.me"
private val apiUrl = "https://a.mangafun.me/v0"
override val lang = "en"
override val supportsLatest = true
override val client = network.cloudflareClient
override fun headersBuilder() = super.headersBuilder()
.add("Referer", "$baseUrl/")
.add("Origin", baseUrl)
private val json: Json by injectLazy()
private val nextBuildId by lazy {
val document = client.newCall(GET(baseUrl, headers)).execute().asJsoup()
json.parseToJsonElement(
document.selectFirst("#__NEXT_DATA__")!!.data(),
)
.jsonObject["buildId"]!!
.jsonPrimitive
.content
}
private lateinit var directory: List<MinifiedMangaDto>
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
return if (page == 1) {
client.newCall(popularMangaRequest(page))
.asObservableSuccess()
.map { popularMangaParse(it) }
} else {
Observable.just(parseDirectory(page))
}
}
override fun popularMangaRequest(page: Int) = GET("$apiUrl/title/all", headers)
override fun popularMangaParse(response: Response): MangasPage {
directory = response.parseAs<List<MinifiedMangaDto>>()
.sortedBy { it.rank }
return parseDirectory(1)
}
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> {
return if (page == 1) {
client.newCall(latestUpdatesRequest(page))
.asObservableSuccess()
.map { latestUpdatesParse(it) }
} else {
Observable.just(parseDirectory(page))
}
}
override fun latestUpdatesRequest(page: Int) = popularMangaRequest(page)
override fun latestUpdatesParse(response: Response): MangasPage {
directory = response.parseAs<List<MinifiedMangaDto>>()
.sortedByDescending { MangaFunUtils.convertShortTime(it.updatedAt) }
return parseDirectory(1)
}
override fun fetchSearchManga(
page: Int,
query: String,
filters: FilterList,
): Observable<MangasPage> {
return if (query.startsWith(PREFIX_ID_SEARCH)) {
val slug = query.removePrefix(PREFIX_ID_SEARCH)
return fetchMangaDetails(SManga.create().apply { url = "/title/$slug" })
.map { MangasPage(listOf(it), false) }
} else if (page == 1) {
client.newCall(searchMangaRequest(page, query, filters))
.asObservableSuccess()
.map { searchMangaParse(it, query, filters) }
} else {
Observable.just(parseDirectory(page))
}
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
popularMangaRequest(page)
override fun searchMangaParse(response: Response) = throw UnsupportedOperationException()
private fun searchMangaParse(response: Response, query: String, filters: FilterList): MangasPage {
directory = response.parseAs<List<MinifiedMangaDto>>()
.filter {
it.name.contains(query, false) ||
it.alias.any { a -> a.contains(query, false) }
}
filters.ifEmpty { getFilterList() }.forEach { filter ->
when (filter) {
is GenreFilter -> {
val included = mutableListOf<Int>()
val excluded = mutableListOf<Int>()
filter.state.forEach { g ->
when (g.state) {
Filter.TriState.STATE_INCLUDE -> included.add(g.id)
Filter.TriState.STATE_EXCLUDE -> excluded.add(g.id)
}
}
if (included.isNotEmpty()) {
directory = directory
.filter { it.genres.any { g -> included.contains(g) } }
}
if (excluded.isNotEmpty()) {
directory = directory
.filterNot { it.genres.any { g -> excluded.contains(g) } }
}
}
is TypeFilter -> {
val included = mutableListOf<Int>()
val excluded = mutableListOf<Int>()
filter.state.forEach { g ->
when (g.state) {
Filter.TriState.STATE_INCLUDE -> included.add(g.id)
Filter.TriState.STATE_EXCLUDE -> excluded.add(g.id)
}
}
if (included.isNotEmpty()) {
directory = directory
.filter { included.any { t -> it.titleType == t } }
}
if (excluded.isNotEmpty()) {
directory = directory
.filterNot { excluded.any { t -> it.titleType == t } }
}
}
is StatusFilter -> {
val included = mutableListOf<Int>()
val excluded = mutableListOf<Int>()
filter.state.forEach { g ->
when (g.state) {
Filter.TriState.STATE_INCLUDE -> included.add(g.id)
Filter.TriState.STATE_EXCLUDE -> excluded.add(g.id)
}
}
if (included.isNotEmpty()) {
directory = directory
.filter { included.any { t -> it.publishedStatus == t } }
}
if (excluded.isNotEmpty()) {
directory = directory
.filterNot { excluded.any { t -> it.publishedStatus == t } }
}
}
is SortFilter -> {
directory = when (filter.state?.index) {
0 -> directory.sortedBy { it.name }
1 -> directory.sortedBy { it.rank }
2 -> directory.sortedBy { MangaFunUtils.convertShortTime(it.createdAt) }
3 -> directory.sortedBy { MangaFunUtils.convertShortTime(it.updatedAt) }
else -> throw IllegalStateException("Unhandled sort option")
}
if (filter.state?.ascending != true) {
directory = directory.reversed()
}
}
else -> {}
}
}
return parseDirectory(1)
}
override fun getMangaUrl(manga: SManga) = "$baseUrl${manga.url}"
override fun mangaDetailsRequest(manga: SManga): Request {
val slug = manga.url.substringAfterLast("/")
val nextDataUrl = "$baseUrl/_next/data/$nextBuildId/title/$slug.json"
return GET(nextDataUrl, headers)
}
override fun mangaDetailsParse(response: Response): SManga {
val data = response.parseAs<NextPagePropsWrapperDto>()
.pageProps
.dehydratedState
.queries
.first()
.state
.data
return json.decodeFromJsonElement<MangaDto>(data).toSManga()
}
override fun chapterListRequest(manga: SManga) = mangaDetailsRequest(manga)
override fun chapterListParse(response: Response): List<SChapter> {
val data = response.parseAs<NextPagePropsWrapperDto>()
.pageProps
.dehydratedState
.queries
.first()
.state
.data
val mangaData = json.decodeFromJsonElement<MangaDto>(data)
return mangaData.chapters.map { it.toSChapter(mangaData.id, mangaData.name) }.reversed()
}
override fun getChapterUrl(chapter: SChapter) = "$baseUrl${chapter.url}"
override fun pageListRequest(chapter: SChapter): Request {
val chapterId = chapter.url.substringAfterLast("/").substringBefore("-")
return GET("$apiUrl/chapter/$chapterId", headers)
}
override fun pageListParse(response: Response): List<Page> {
val encoded = Base64.encode(response.body.bytes(), Base64.DEFAULT or Base64.NO_WRAP).toString(Charsets.UTF_8)
val decoded = LZString.decompressFromBase64(encoded)
val compressedJson = json.parseToJsonElement(decoded).jsonArray
val decompressedJson = DecompressJson.decompress(compressedJson).jsonObject
Log.d("MangaFun", Json.encodeToString(decompressedJson))
return decompressedJson.jsonObject["p"]!!.jsonArray.mapIndexed { i, it ->
Page(i, imageUrl = MangaFunUtils.getImageUrlFromHash(it.jsonArray[0].jsonPrimitive.content))
}
}
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
override fun getFilterList() = FilterList(
GenreFilter(),
TypeFilter(),
StatusFilter(),
SortFilter(),
)
private fun parseDirectory(page: Int): MangasPage {
val endRange = min((page * 24), directory.size)
val manga = directory.subList(((page - 1) * 24), endRange).map { it.toSManga() }
val hasNextPage = endRange < directory.lastIndex
return MangasPage(manga, hasNextPage)
}
private inline fun <reified T> Response.parseAs(): T =
json.decodeFromString(body.string())
companion object {
internal const val PREFIX_ID_SEARCH = "id:"
internal const val MANGAFUN_EPOCH = 1693473000
}
}

View File

@ -1,70 +0,0 @@
package eu.kanade.tachiyomi.extension.en.mangafun
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
@Serializable
data class MinifiedMangaDto(
@SerialName("i") val id: Int,
@SerialName("n") val name: String,
@SerialName("t") val thumbnailUrl: String? = null,
@SerialName("s") val publishedStatus: Int = 0,
@SerialName("tt") val titleType: Int = 0,
@SerialName("a") val alias: List<String> = emptyList(),
@SerialName("g") val genres: List<Int> = emptyList(),
@SerialName("au") val author: List<String> = emptyList(),
@SerialName("r") val rank: Int = 999999999,
@SerialName("ca") val createdAt: Int = 0,
@SerialName("ua") val updatedAt: Int = 0,
)
@Serializable
data class MangaDto(
val id: Int,
val name: String,
val thumbnailURL: String? = null,
val publishedStatus: Int = 0,
val titleType: Int = 0,
val alias: List<String>,
val description: String,
val genres: List<GenreDto>,
val artist: List<String?>,
val author: List<String?>,
val chapters: List<ChapterDto>,
)
@Serializable
data class ChapterDto(
val id: Int,
val name: String,
val publishedAt: String,
)
@Serializable
data class GenreDto(val id: Int, val name: String)
@Serializable
data class NextPagePropsWrapperDto(
val pageProps: NextPagePropsDto,
)
@Serializable
data class NextPagePropsDto(
val dehydratedState: DehydratedStateDto,
)
@Serializable
data class DehydratedStateDto(
val queries: List<QueriesDto>,
)
@Serializable
data class QueriesDto(
val state: StateDto,
)
@Serializable
data class StateDto(
val data: JsonElement,
)

View File

@ -1,149 +0,0 @@
package eu.kanade.tachiyomi.extension.en.mangafun
import eu.kanade.tachiyomi.source.model.Filter
class GenreFilter : Filter.Group<Genre>("Genre", genreList)
class TypeFilter : Filter.Group<Genre>("Type", titleTypeList)
class StatusFilter : Filter.Group<Genre>(
"Status",
listOf("Ongoing", "Completed", "Hiatus", "Cancelled").mapIndexed { i, it -> Genre(it, i) },
)
class SortFilter : Filter.Sort(
"Order by",
arrayOf("Name", "Rank", "Newest", "Update"),
Selection(1, false),
)
class Genre(name: String, val id: Int) : Filter.TriState(name)
val genresMap by lazy {
genreList.associate { it.id to it.name }
}
val titleTypeMap by lazy {
titleTypeList.associate { it.id to it.name }
}
val titleTypeList by lazy {
listOf(
Genre("Manga", 0),
Genre("Manhwa", 1),
Genre("Manhua", 2),
Genre("Comic", 3),
Genre("Webtoon", 4),
Genre("One Shot", 6),
Genre("Doujinshi", 7),
Genre("Other", 8),
)
}
val genreList by lazy {
listOf(
Genre("Supernatural", 1),
Genre("Action", 2),
Genre("Comedy", 3),
Genre("Josei", 4),
Genre("Martial Arts", 5),
Genre("Romance", 6),
Genre("Ecchi", 7),
Genre("Harem", 8),
Genre("School Life", 9),
Genre("Seinen", 10),
Genre("Adventure", 11),
Genre("Fantasy", 12),
Genre("Demons", 13),
Genre("Magic", 14),
Genre("Military", 15),
Genre("Shounen", 16),
Genre("Shoujo", 17),
Genre("Psychological", 18),
Genre("Drama", 19),
Genre("Mystery", 20),
Genre("Sci-Fi", 21),
Genre("Slice of Life", 22),
Genre("Doujinshi", 23),
Genre("Police", 24),
Genre("Mecha", 25),
Genre("Yaoi", 26),
Genre("Horror", 27),
Genre("Historical", 28),
Genre("Thriller", 29),
Genre("Shounen Ai", 30),
Genre("Game", 31),
Genre("Gender Bender", 32),
Genre("Sports", 33),
Genre("Yuri", 34),
Genre("Music", 35),
Genre("Shoujo Ai", 36),
Genre("Vampires", 37),
Genre("Parody", 38),
Genre("Kids", 40),
Genre("Super Power", 41),
Genre("Space", 43),
Genre("Adult", 46),
Genre("Webtoons", 47),
Genre("Mature", 48),
Genre("Smut", 49),
Genre("Tragedy", 51),
Genre("One Shot", 53),
Genre("4-koma", 56),
Genre("Isekai", 58),
Genre("Food", 60),
Genre("Crime", 63),
Genre("Superhero", 67),
Genre("Animals", 69),
Genre("Manhwa", 74),
Genre("Manhua", 75),
Genre("Cooking", 78),
Genre("Medical", 79),
Genre("Magical Girls", 88),
Genre("Monsters", 89),
Genre("Shotacon", 90),
Genre("Philosophical", 91),
Genre("Wuxia", 92),
Genre("Adaptation", 95),
Genre("Full Color", 96),
Genre("Korean", 97),
Genre("Chinese", 98),
Genre("Reincarnation", 100),
Genre("Manga", 102),
Genre("Comic", 104),
Genre("Japanese", 105),
Genre("Time Travel", 108),
Genre("Erotica", 111),
Genre("Survival", 114),
Genre("Gore", 118),
Genre("Monster Girls", 120),
Genre("Dungeons", 123),
Genre("System", 124),
Genre("Cultivation", 125),
Genre("Murim", 128),
Genre("Suggestive", 131),
Genre("Fighting", 134),
Genre("Blood", 140),
Genre("Op-Mc", 142),
Genre("Revenge", 144),
Genre("Overpowered", 146),
Genre("Returner", 150),
Genre("Office", 152),
Genre("Loli", 163),
Genre("Video Games", 173),
Genre("Monster", 199),
Genre("Mafia", 203),
Genre("Anthology", 206),
Genre("Villainess", 207),
Genre("Aliens", 213),
Genre("Zombies", 216),
Genre("Violence", 217),
Genre("Delinquents", 219),
Genre("Post apocalyptic", 255),
Genre("Ghost", 260),
Genre("Virtual Reality", 263),
Genre("Cheat", 324),
Genre("Girls", 374),
Genre("Gender Swap", 384),
)
}

View File

@ -1,33 +0,0 @@
package eu.kanade.tachiyomi.extension.en.mangafun
import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Intent
import android.os.Bundle
import android.util.Log
import kotlin.system.exitProcess
class MangaFunUrlActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val pathSegments = intent?.data?.pathSegments
if (pathSegments != null && pathSegments.size > 1) {
try {
startActivity(
Intent().apply {
action = "eu.kanade.tachiyomi.SEARCH"
putExtra("query", "${MangaFun.PREFIX_ID_SEARCH}${pathSegments[1]}")
putExtra("filter", packageName)
},
)
} catch (e: ActivityNotFoundException) {
Log.e("MangaFunUrlActivity", "Could not start activity", e)
}
} else {
Log.e("MangaFunUrlActivity", "Could not parse URI from intent $intent")
}
finish()
exitProcess(0)
}
}

View File

@ -1,77 +0,0 @@
package eu.kanade.tachiyomi.extension.en.mangafun
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import net.pearx.kasechange.toKebabCase
import java.text.SimpleDateFormat
import java.util.Locale
object MangaFunUtils {
private const val cdnUrl = "https://mimg.bid"
private val notAlnumRegex = Regex("""[^0-9A-Za-z\s]""")
private val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT)
private fun String.slugify(): String =
this.replace(notAlnumRegex, "").toKebabCase()
private fun publishedStatusToStatus(ps: Int) = when (ps) {
0 -> SManga.ONGOING
1 -> SManga.COMPLETED
2 -> SManga.ON_HIATUS
3 -> SManga.CANCELLED
else -> SManga.UNKNOWN
}
fun convertShortTime(value: Int): Int {
return if (value < MangaFun.MANGAFUN_EPOCH) {
value + MangaFun.MANGAFUN_EPOCH
} else {
value
}
}
fun getImageUrlFromHash(hash: String?): String? {
if (hash == null) {
return null
}
return "$cdnUrl/${hash.substring(0, 2)}/${hash.substring(2, 5)}/${hash.substring(5)}.webp"
}
fun MinifiedMangaDto.toSManga() = SManga.create().apply {
url = "/title/$id-${name.slugify()}"
title = name
author = this@toSManga.author.joinToString()
thumbnail_url = getImageUrlFromHash(thumbnailUrl)
status = publishedStatusToStatus(publishedStatus)
genre = buildList {
titleTypeMap[titleType]?.let { add(it) }
addAll(genres.mapNotNull { genresMap[it] })
}.joinToString()
}
fun MangaDto.toSManga() = SManga.create().apply {
url = "/title/$id-${name.slugify()}"
title = name
author = this@toSManga.author.filterNotNull().joinToString()
artist = this@toSManga.artist.filterNotNull().joinToString()
description = this@toSManga.description
genre = genres.mapNotNull { genresMap[it.id] }.joinToString()
status = publishedStatusToStatus(publishedStatus)
thumbnail_url = thumbnailURL
genre = buildList {
titleTypeMap[titleType]?.let { add(it) }
addAll(genres.mapNotNull { genresMap[it.id] })
}.joinToString()
}
fun ChapterDto.toSChapter(mangaId: Int, mangaName: String) = SChapter.create().apply {
url = "/title/$mangaId-${mangaName.slugify()}/$id-${this@toSChapter.name.slugify()}"
name = this@toSChapter.name
date_upload = runCatching {
dateFormat.parse(publishedAt)!!.time
}.getOrDefault(0L)
}
}

View File

@ -1,9 +0,0 @@
ext {
extName = 'Manga Tx.gg (unoriginal)'
extClass = '.MangaTxGg'
themePkg = 'madara'
baseUrl = 'https://mangatx.gg'
overrideVersionCode = 0
}
apply from: "$rootDir/common.gradle"

View File

@ -1,7 +0,0 @@
package eu.kanade.tachiyomi.extension.en.mangatxgg
import eu.kanade.tachiyomi.multisrc.madara.Madara
class MangaTxGg : Madara("Manga Tx.gg (unoriginal)", "https://mangatx.gg", "en") {
override val useNewChapterEndpoint = false
}

View File

@ -1,9 +0,0 @@
ext {
extName = 'Meow Meow Comics'
extClass = '.MeowMeowComics'
themePkg = 'madara'
baseUrl = 'https://meowmeowcomics.com'
overrideVersionCode = 0
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,34 +0,0 @@
package eu.kanade.tachiyomi.extension.en.meowmeowcomics
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Request
import okhttp3.Response
class MeowMeowComics : Madara(
"Meow Meow Comics",
"https://meowmeowcomics.com",
"en",
) {
override val client = super.client.newBuilder()
.rateLimit(2)
.build()
// ============================== Chapters ==============================
override fun chapterListRequest(manga: SManga): Request {
return xhrChaptersRequest(baseUrl + manga.url.removeSuffix("/"))
}
override fun chapterListParse(response: Response): List<SChapter> {
return response.asJsoup()
.select("ul.main > li.parent,ul.main:not(:has(>li.parent))")
.sortedByDescending { it.selectFirst("a.has-child")?.text()?.toIntOrNull() ?: 0 }
.flatMap { season ->
season.select(chapterListSelector()).map(::chapterFromElement)
}
}
}

View File

@ -1,9 +0,0 @@
ext {
extName = 'Night Comic'
extClass = '.NightComic'
themePkg = 'madara'
baseUrl = 'https://nightcomic.com'
overrideVersionCode = 2
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@ -1,8 +0,0 @@
package eu.kanade.tachiyomi.extension.en.nightcomic
import eu.kanade.tachiyomi.multisrc.madara.Madara
class NightComic : Madara("Night Comic", "https://nightcomic.com", "en") {
override val useNewChapterEndpoint = true
override val mangaDetailsSelectorAuthor = "div.manga-authors > a"
}

View File

@ -1,7 +0,0 @@
ext {
extName = 'Rmanga.app'
extClass = '.Rmanga'
extVersionCode = 2
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,186 +0,0 @@
package eu.kanade.tachiyomi.extension.en.rmanga
import android.app.Application
import android.content.SharedPreferences
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.model.Filter
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.FormBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class Rmanga : ConfigurableSource, ParsedHttpSource() {
override val name = "Rmanga.app"
override val lang = "en"
override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.rateLimit(4)
.build()
private val preferences: SharedPreferences =
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
override val baseUrl = preferences.getString(DOMAIN_PREF, "https://rmanga.app")!!
override fun headersBuilder() = super.headersBuilder()
.add("Referer", baseUrl)
override fun popularMangaRequest(page: Int): Request {
return GET("$baseUrl/ranking/most-viewed/$page", headers)
}
override fun popularMangaSelector() = "div.category-items > ul > li"
override fun popularMangaFromElement(element: Element): SManga {
return SManga.create().apply {
element.select("div.category-name a").let {
setUrlWithoutDomain(it.attr("href"))
title = it.text()
}
thumbnail_url = element.select("img").attr("abs:src")
}
}
override fun popularMangaNextPageSelector() = "a.pagination__item:contains(»)"
override fun latestUpdatesRequest(page: Int): Request {
return GET("$baseUrl/latest-updates/$page", headers)
}
override fun latestUpdatesParse(response: Response): MangasPage {
return super.latestUpdatesParse(response).apply {
this.mangas.distinctBy { it.url }
}
}
override fun latestUpdatesSelector() = "div.latest-updates > ul > li"
override fun latestUpdatesFromElement(element: Element): SManga {
return SManga.create().apply {
element.select("div.latest-updates-name a").let {
setUrlWithoutDomain(it.attr("href"))
title = it.text()
}
thumbnail_url = element.select("img").attr("abs:src")
}
}
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val payload = FormBody.Builder().apply {
add("manga-name", query.trim())
filters.forEach { filter ->
when (filter) {
is TypeFilter -> {
add("type", filter.getValue())
}
is AuthorFilter -> {
add("author-name", filter.state.trim())
}
is ArtistFilter -> {
add("artist-name", filter.state.trim())
}
is StatusFilter -> {
add("status", filter.getValue())
}
is GenreFilter -> {
filter.state.forEach { genreState ->
when (genreState.state) {
Filter.TriState.STATE_INCLUDE -> add("include[]", genreState.id)
Filter.TriState.STATE_EXCLUDE -> add("exclude[]", genreState.id)
}
}
}
else -> {}
}
}
}.build()
return POST("$baseUrl/detailed-search", headers, payload)
}
override fun getFilterList() = getFilters()
override fun searchMangaFromElement(element: Element) = popularMangaFromElement(element)
override fun searchMangaSelector() = popularMangaSelector()
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
override fun mangaDetailsParse(document: Document): SManga {
return SManga.create().apply {
title = document.select("div.section-header-title").first()!!.text()
description = document.select("div.empty-box").eachText().joinToString("\n\n", postfix = "\n\n")
thumbnail_url = document.select("div.novels-detail-left img").attr("abs:src")
document.select("div.novels-detail-right > ul").let { element ->
author = element.select("li:contains(author)").text().substringAfter(":").trim().takeUnless { it == "N/A" }
artist = element.select("li:contains(artist)").text().substringAfter(":").trim().takeUnless { it == "N/A" }
genre = element.select("li:contains(genres) a").joinToString { it.text() }
status = element.select("li:contains(status)").text().parseStatus()
description += element.select("li:contains(alternative)").text()
}
}
}
private fun String.parseStatus(): Int {
return when {
this.contains("ongoing", true) -> SManga.ONGOING
this.contains("completed", true) -> SManga.COMPLETED
else -> SManga.UNKNOWN
}
}
override fun chapterListSelector() = "div.novels-detail-chapters a"
override fun chapterFromElement(element: Element): SChapter {
return SChapter.create().apply {
setUrlWithoutDomain(element.attr("href"))
name = element.ownText()
}
}
override fun pageListParse(document: Document): List<Page> {
return document.select("div.chapter-detail-novel-big-image img").mapIndexed { index, img ->
Page(index = index, imageUrl = img.attr("abs:src"))
}
}
override fun imageUrlParse(document: Document): String {
throw UnsupportedOperationException()
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
ListPreference(screen.context).apply {
key = DOMAIN_PREF
title = "Preferred domain"
entries = arrayOf("rmanga.app", "readmanga.app")
entryValues = arrayOf("https://rmanga.app", "https://readmanga.app")
setDefaultValue("https://rmanga.app")
summary = "Requires App Restart"
}.let { screen.addPreference(it) }
}
companion object {
private const val DOMAIN_PREF = "pref_domain"
}
}

View File

@ -1,95 +0,0 @@
package eu.kanade.tachiyomi.extension.en.rmanga
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
class Genre(
name: String,
val id: String,
) : Filter.TriState(name)
internal class GenreFilter(name: String, genres: List<Genre>) :
Filter.Group<Genre>(name, genres)
private val genreList = listOf(
Genre("Action", "1"),
Genre("Adventure", "23"),
Genre("All Categories", "42"),
Genre("Comedy", "12"),
Genre("Cooking", "51"),
Genre("Doujinshi", "26"),
Genre("Drama", "9"),
Genre("Ecchi", "2"),
Genre("Fantasy", "3"),
Genre("Gender Bender", "30"),
Genre("Harem", "4"),
Genre("Historical", "36"),
Genre("Horror", "34"),
Genre("Isekai", "44"),
Genre("Josei", "17"),
Genre("Lolicon", "39"),
Genre("Magic", "48"),
Genre("Manga", "5"),
Genre("Manhua", "31"),
Genre("Manhwa", "32"),
Genre("Martial Arts", "22"),
Genre("Mature", "50"),
Genre("Mecha", "33"),
Genre("Mind Game", "52"),
Genre("Mystery", "13"),
Genre("None", "41"),
Genre("One shot", "16"),
Genre("Psychological", "14"),
Genre("Recarnation", "49"),
Genre("Romance", "6"),
Genre("School Life", "10"),
Genre("Sci fi", "19"),
Genre("Seinen", "24"),
Genre("Shotacon", "38"),
Genre("Shoujo", "8"),
Genre("Shoujo Ai", "37"),
Genre("Shounen", "7"),
Genre("Shounen Ai", "35"),
Genre("Slice of Life", "21"),
Genre("Sports", "29"),
Genre("Supernatural", "11"),
Genre("Time Travel", "45"),
Genre("Tragedy", "15"),
Genre("Uncategorized", "43"),
Genre("Yaoi", "28"),
Genre("Yuri", "20"),
)
internal class TypeFilter(name: String, private val types: Array<String>) :
Filter.Select<String>(name, types) {
fun getValue() = types[state]
}
private val typeFilter: Array<String> = arrayOf(
"All",
"Japanese",
"Korean",
"Chinese",
)
internal class AuthorFilter(title: String) : Filter.Text(title)
internal class ArtistFilter(title: String) : Filter.Text(title)
internal class StatusFilter(name: String, private val status: Array<String>) :
Filter.Select<String>(name, status) {
fun getValue() = status[state]
}
private val statusFilter: Array<String> = arrayOf(
"Both",
"Ongoing",
"Completed",
)
fun getFilters() = FilterList(
TypeFilter("Type", typeFilter),
AuthorFilter("Author"),
ArtistFilter("Artist"),
StatusFilter("Status", statusFilter),
GenreFilter("Genres", genreList),
)

View File

@ -1,7 +0,0 @@
ext {
extName = 'Silent Manga Audition'
extClass = '.SilentMangaAudition'
extVersionCode = 5
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,156 +0,0 @@
package eu.kanade.tachiyomi.extension.en.silentmangaaudition
import eu.kanade.tachiyomi.source.model.SManga
data class SmaEntry(
val name: String,
val url: String,
val chapterListUrl: String,
val thumbnailUrl: String,
) {
fun toSManga(index: Int): SManga = SManga.create().apply {
title = name
author = "Various artists"
status = SManga.COMPLETED
description = "The theme is… " + name.substringAfter(" ") + "."
thumbnail_url = thumbnailUrl
url = "${this@SmaEntry.url},$chapterListUrl,$index"
initialized = true
}
}
val SMA_ENTRIES = listOf(
SmaEntry(
"SMA-17 “MOMENTS of HASTE, RAGE or SMILES”",
"/sma17-silent-manga-audition-2022-results-announcement",
"/v/sma17/bones-by-rimui/?lang=en",
"https://www.manga-audition.com/wp/wp-content/themes/gridlove-child/assets/img/award-result/sma17/header_sp.png",
),
SmaEntry(
"SMA-16 “MOMENTS of FEAR, JOY, or LOVE”",
"/sma16-silent-manga-audition-2021-results-announcement",
"/v/sma16/lacrimosa-by-laica-chrose/?lang=en",
"https://www.manga-audition.com/wp/wp-content/uploads/2021/11/hero_sp_new.jpg",
),
SmaEntry(
"SMA-15 “Moments of CRYING, SMILING or LOVE”",
"/sma15-silent-manga-audition-2021-award-winners",
"/v/sma15/blossom-by-enewald/?lang=en",
"https://www.manga-audition.com/wp/wp-content/themes/gridlove-child/assets/img/award-result/sma15/header_sp.png",
),
SmaEntry(
"SMA-14 “Creature, Spirits & Monsters”",
"/sma14-silent-manga-audition-2020-award-winners",
"/v/sma14/blooming-flower-by-blackwink/",
"https://www.manga-audition.com/wp/wp-content/themes/gridlove-child/assets/img/award-result/sma14/header_sp.png",
),
SmaEntry(
"SMA-13 “Together for peace”",
"/sma13-silent-manga-audition-2020-award-winners/",
"/v/sma13/homeless-by-simone-sanseverino/?lang=en",
"https://www.manga-audition.com/wp/wp-content/themes/gridlove-child/assets/img/award-result/sma13/header_sp.png",
),
SmaEntry(
"SMA-12 “New beginning”",
"/sma12-silent-manga-audition-2019-award-winners/",
"/v/sma12/never-late-by-lucas-marques-and-priscilla-miranda/?lang=en",
"https://www.manga-audition.com/wp/wp-content/themes/gridlove-child/assets/img/award-result/sma12/header_sp.png",
),
SmaEntry(
"SMA-EX5 “Kumamoto + Do Your Best!”",
"/smaex5-silent-manga-audition-2019-award-winners/",
"/v/smaex5/fish-by-youngman/",
"https://www.manga-audition.com/wp/wp-content/themes/gridlove-child/assets/img/award-result/smaex5/top_banner_sp.jpg",
),
SmaEntry(
"SMA11 “Promise”",
"/sma11-silent-manga-audition-2019-award-winners/",
"/v/sma11/reborn-by-riza-al-assami/?lang=en",
"https://www.manga-audition.com/wp/wp-content/themes/gridlove-child/assets/img/award-result/sma11/top_banner_sp.jpg",
),
SmaEntry(
"SMA-EX4 “Kit Kat ROUND”",
"/smaex4-2018award/",
"/v/smaex4/lucky-charm-by-harihtaroon/",
"https://s3-ap-northeast-1.amazonaws.com/data.smacmag.net/_images/sma_page/pc/smaex4/smaex4_main01.png",
),
SmaEntry(
"SMA10 “Effort / Friendship / Victory”",
"/sma10-2018award-2/",
"/v/sma10/run-by-riza-al-assami/?lang=en",
"https://s3-ap-northeast-1.amazonaws.com/data.smacmag.net/_images/sma_page/sma10/sma10main_3.png",
),
SmaEntry(
"SMA-EX3 “Kumamoto + Wasamon”",
"/smaex3-2018award/",
"/v/smaex3/to-the-sky-by-zevania-and-nattorin/",
"https://s3-ap-northeast-1.amazonaws.com/data.smacmag.net/_images/sma_page/pc/smaex3/smaex3_main01.png",
),
SmaEntry(
"SMA9 “Fairness / Respect / Teamwork”",
"/sma9-2018award/",
"/v/sma9/fisherman-tales-by-joao-eddie/",
"https://s3-ap-northeast-1.amazonaws.com/data.smacmag.net/_images/sma_page/pc/sma9/sma9_theme.png",
),
SmaEntry(
"SMA8 “Fair Play”",
"/sma8-2017award/",
"/v/sma8/checkmate-by-sideburn004/",
"https://s3-ap-northeast-1.amazonaws.com/data.smacmag.net/_images/sma_page/pc/sma8/sma8_theme.png",
),
SmaEntry(
"SMA7 “Unforgettable Taste”",
"/sma7-2017award/",
"/v/sma7/our-promised-land-by-nattorin-and-zevania/",
"https://s3-ap-northeast-1.amazonaws.com/data.smacmag.net/_images/sma_page/pc/sma7/sma7_theme.png",
),
SmaEntry(
"SMA-EX2 “Kumamoto + Smile”",
"http://data.smacmag.net/sma/smaex2-2017award/",
"https://smacmag.net/v/sma2/drawing-a-smile-out-by-dee-juusan/",
"http://data.smacmag.net/sma/smaex2-2017award/images/smaex2_title.png",
),
SmaEntry(
"SMA6 “Childhood”",
"/sma6-2016award/",
"/v/sma6/forbidden-by-yos/13828",
"https://s3-ap-northeast-1.amazonaws.com/data.smacmag.net/_images/sma_page/pc/sma6/SMA06_themes.png",
),
SmaEntry(
"SMA5 “Friend-ship + Communication Tool”",
"/sma05-2016award/",
"/v/sma5/im-happy-by-ds-studio/11915",
"https://s3-ap-northeast-1.amazonaws.com/data.smacmag.net/_images/sma_page/pc/sma5/sma5_theme.png",
),
SmaEntry(
"SMA-EX1 “Fukushima Sakuramori”",
"/smaex1-2016award/",
"/v/smaex1/seeds-by-jim/9574",
"https://s3-ap-northeast-1.amazonaws.com/data.smacmag.net/_images/sma_page/pc/smaex1/smaex1_theme.png",
),
SmaEntry(
"SMA4 “A Charming Gift”",
"/sma04-2015award/",
"/v/sma4/birdy-by-kalongzz/",
"https://s3-ap-northeast-1.amazonaws.com/data.smacmag.net/_images/sma_page/pc/sma4/sma4_theme.png",
),
SmaEntry(
"SMA3 “Mother”",
"/sma03-2015award/",
"/v/sma3/homesick-alien-by-ichirou/4390",
"https://s3-ap-northeast-1.amazonaws.com/data.smacmag.net/_images/sma_page/pc/sma3/sma3_theme.png",
),
SmaEntry(
"SMA2 “The Finest Smile”",
"/sma02-2014award/",
"/v/sma2/fathers-gift-by-ichirou/1775",
"https://s3-ap-northeast-1.amazonaws.com/data.smacmag.net/_images/sma_page/pc/sma2/sma2_theme.png",
),
SmaEntry(
"SMA1 “Love Letter”",
"/sma01-2013award/",
"/v/sma1/excuse-me-by-alex-irzaqi/",
"https://s3-ap-northeast-1.amazonaws.com/data.smacmag.net/_images/sma_page/pc/sma1/sma1_theme.png",
),
)

View File

@ -1,125 +0,0 @@
package eu.kanade.tachiyomi.extension.en.silentmangaaudition
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.Headers
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Element
import rx.Observable
class SilentMangaAudition : HttpSource() {
override val name = "Silent Manga Audition"
override val baseUrl = "https://manga-audition.com"
override val lang = "en"
override val supportsLatest = false
override fun headersBuilder(): Headers.Builder = Headers.Builder()
.add("User-Agent", USER_AGENT)
.add("Referer", baseUrl)
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
val entries = SMA_ENTRIES.mapIndexed { i, entry -> entry.toSManga(i) }
return Observable.just(MangasPage(entries, false))
}
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
val filteredEntries = SMA_ENTRIES
.mapIndexed { i, entry -> entry.toSManga(i) }
.filter {
it.title.contains(query, true) ||
it.description!!.contains(query, true)
}
return Observable.just(MangasPage(filteredEntries, false))
}
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
val index = manga.url.substringAfterLast(",").toInt()
val entry = SMA_ENTRIES[index]
return Observable.just(entry.toSManga(index))
}
override fun mangaDetailsRequest(manga: SManga): Request {
val url = manga.url.substringBefore(",")
return GET(if (url.startsWith("/")) baseUrl + url else url, headers)
}
override fun chapterListRequest(manga: SManga): Request {
val url = manga.url
.substringAfter(",")
.substringBefore(",")
return GET(SMACMAG_URL + url, headers)
}
override fun chapterListParse(response: Response): List<SChapter> {
return response.asJsoup()
.select(chapterListSelector())
.map { chapterFromElement(it) }
}
private fun chapterListSelector(): String = "ol.playlist li a"
private fun chapterFromElement(element: Element): SChapter = SChapter.create().apply {
name = element.select("span.ttl").text()
scanlator = element.select("span.name").text()
url = element.attr("abs:href")
}
override fun pageListRequest(chapter: SChapter): Request {
return GET(chapter.url, headers)
}
override fun pageListParse(response: Response): List<Page> {
val chapterUrl = response.request.url.toString()
return response.asJsoup()
.select("div.swiper-wrapper div.swiper-slide img.swiper-lazy")
.mapIndexed { i, element -> Page(i, chapterUrl, element.attr("data-src")) }
}
override fun fetchImageUrl(page: Page): Observable<String> = Observable.just(page.imageUrl!!)
override fun imageUrlParse(response: Response): String = ""
override fun imageRequest(page: Page): Request {
val newHeaders = headersBuilder()
.set("Referer", page.url)
.build()
return GET(page.imageUrl!!, newHeaders)
}
override fun popularMangaRequest(page: Int): Request = throw UnsupportedOperationException()
override fun popularMangaParse(response: Response): MangasPage = throw UnsupportedOperationException()
override fun latestUpdatesRequest(page: Int): Request = throw UnsupportedOperationException()
override fun latestUpdatesParse(response: Response): MangasPage = throw UnsupportedOperationException()
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = throw UnsupportedOperationException()
override fun searchMangaParse(response: Response): MangasPage = throw UnsupportedOperationException()
override fun mangaDetailsParse(response: Response): SManga = throw UnsupportedOperationException()
companion object {
private const val SMACMAG_URL = "https://smacmag.net"
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36"
}
}

View File

@ -1,9 +0,0 @@
ext {
extName = 'Silent Sky'
extClass = '.SilentSky'
themePkg = 'foolslide'
baseUrl = 'https://reader.silentsky-scans.net'
overrideVersionCode = 0
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

View File

@ -1,5 +0,0 @@
package eu.kanade.tachiyomi.extension.en.silentsky
import eu.kanade.tachiyomi.multisrc.foolslide.FoolSlide
class SilentSky : FoolSlide("Silent Sky", "https://reader.silentsky-scans.net", "en")

View File

@ -1,9 +0,0 @@
ext {
extName = 'Solo Leveling'
extClass = '.SoloLeveling'
themePkg = 'madara'
baseUrl = 'https://readsololeveling.online'
overrideVersionCode = 0
}
apply from: "$rootDir/common.gradle"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

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