Compare commits

..

No commits in common. "d61cbfc0c18a50f7b9805c3dfc01d102f69e353d" and "c353c9a78007329827ba41b637cb160005e0fcf7" have entirely different histories.

683 changed files with 2333 additions and 2944 deletions

View File

@ -7,4 +7,3 @@ Checklist:
- [ ] Have not changed source names
- [ ] Have explicitly kept the `id` if a source's name or language were changed
- [ ] Have tested the modifications by compiling and running the extension through Android Studio
- [ ] Have removed `web_hi_res_512.png` when adding a new extension

View File

@ -37,8 +37,8 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: 17
distribution: temurin
java-version: 11
distribution: adopt
- name: Prepare signing key
run: |
@ -82,8 +82,8 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: 17
distribution: temurin
java-version: 11
distribution: adopt
- name: Prepare signing key
run: |
@ -125,7 +125,7 @@ jobs:
uses: actions/setup-java@v3
with:
java-version: 17
distribution: temurin
distribution: adopt
- name: Checkout master branch
uses: actions/checkout@v4

View File

@ -6,54 +6,31 @@ This guide is not definitive and it's being updated over time. If you find any i
## Table of Contents
- [Contributing](#contributing)
- [Table of Contents](#table-of-contents)
- [Prerequisites](#prerequisites)
- [Tools](#tools)
- [Cloning the repository](#cloning-the-repository)
- [Getting help](#getting-help)
- [Writing an extension](#writing-an-extension)
- [Setting up a new Gradle module](#setting-up-a-new-gradle-module)
- [Loading a subset of Gradle modules](#loading-a-subset-of-gradle-modules)
- [Extension file structure](#extension-file-structure)
- [AndroidManifest.xml](#androidmanifestxml)
- [build.gradle](#buildgradle)
- [Core dependencies](#core-dependencies)
- [Extension API](#extension-api)
- [DataImage library](#dataimage-library)
- [i18n library](#i18n-library)
- [Additional dependencies](#additional-dependencies)
- [Extension main class](#extension-main-class)
- [Main class key variables](#main-class-key-variables)
- [Extension call flow](#extension-call-flow)
- [Popular Manga](#popular-manga)
- [Latest Manga](#latest-manga)
- [Manga Search](#manga-search)
- [Filters](#filters)
- [Manga Details](#manga-details)
- [Chapter](#chapter)
- [Chapter Pages](#chapter-pages)
- [Misc notes](#misc-notes)
- [Advanced Extension features](#advanced-extension-features)
- [URL intent filter](#url-intent-filter)
- [Update strategy](#update-strategy)
- [Renaming existing sources](#renaming-existing-sources)
- [Multi-source themes](#multi-source-themes)
- [The directory structure](#the-directory-structure)
- [Development workflow](#development-workflow)
- [Scaffolding overrides](#scaffolding-overrides)
- [Additional Notes](#additional-notes)
- [Running](#running)
- [Debugging](#debugging)
- [Android Debugger](#android-debugger)
- [Logs](#logs)
- [Inspecting network calls](#inspecting-network-calls)
- [Using external network inspecting tools](#using-external-network-inspecting-tools)
- [Setup your proxy server](#setup-your-proxy-server)
- [OkHttp proxy setup](#okhttp-proxy-setup)
- [Building](#building)
- [Submitting the changes](#submitting-the-changes)
- [Pull Request checklist](#pull-request-checklist)
1. [Prerequisites](#prerequisites)
1. [Tools](#tools)
2. [Cloning the repository](#cloning-the-repository)
2. [Getting help](#getting-help)
3. [Writing an extension](#writing-an-extension)
1. [Setting up a new Gradle module](#setting-up-a-new-gradle-module)
2. [Core dependencies](#core-dependencies)
3. [Extension main class](#extension-main-class)
4. [Extension call flow](#extension-call-flow)
5. [Misc notes](#misc-notes)
6. [Advanced extension features](#advanced-extension-features)
4. [Multi-source themes](#multi-source-themes)
1. [The directory structure](#the-directory-structure)
2. [Development workflow](#development-workflow)
3. [Scaffolding overrides](#scaffolding-overrides)
4. [Additional Notes](#additional-notes)
5. [Running](#running)
6. [Debugging](#debugging)
1. [Android Debugger](#android-debugger)
2. [Logs](#logs)
3. [Inspecting network calls](#inspecting-network-calls)
4. [Using external network inspecting tools](#using-external-network-inspecting-tools)
7. [Building](#building)
8. [Submitting the changes](#submitting-the-changes)
1. [Pull Request checklist](#pull-request-checklist)
## Prerequisites
@ -224,8 +201,9 @@ src/<lang>/<mysourcename>/
│   │   └── ic_launcher.png
│   ├── mipmap-xxhdpi
│   │   └── ic_launcher.png
│   └── mipmap-xxxhdpi
│      └── ic_launcher.png
│   ├── mipmap-xxxhdpi
│   │   └── ic_launcher.png
│   └── web_hi_res_512.png
└── src
└── eu
└── kanade
@ -245,6 +223,9 @@ A minimal [Android manifest file](https://developer.android.com/guide/topics/man
Make sure that your new extension's `build.gradle` file follows the following structure:
```gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
ext {
extName = '<My source name>'
pkgNameSuffix = '<lang>.<mysourcename>'
@ -434,15 +415,10 @@ open class UriPartFilter(displayName: String, private val vals: Array<Pair<Strin
### Misc notes
- Sometimes you may find no use for some inherited methods. If so just override them and throw
exceptions: `throw UnsupportedOperationException()`
- You probably will find `getUrlWithoutDomain` useful when parsing the target source URLs. Keep in
mind there's a current issue with spaces in the URL though, so if you use it, replace all spaces with
URL encoded characters (like `%20`).
- If possible try to stick to the general workflow from `HttpSource`/`ParsedHttpSource`; breaking
them may cause you more headache than necessary.
- By implementing `ConfigurableSource` you can add settings to your source, which is backed by
[`SharedPreferences`](https://developer.android.com/reference/android/content/SharedPreferences).
- Sometimes you may find no use for some inherited methods. If so just override them and throw exceptions: `throw UnsupportedOperationException("Not used.")`
- You probably will find `getUrlWithoutDomain` useful when parsing the target source URLs. Keep in mind there's a current issue with spaces in the URL though, so if you use it, replace all spaces with URL encoded characters (like `%20`).
- If possible try to stick to the general workflow from `HttpSource`/`ParsedHttpSource`; breaking them may cause you more headache than necessary.
- By implementing `ConfigurableSource` you can add settings to your source, which is backed by [`SharedPreferences`](https://developer.android.com/reference/android/content/SharedPreferences).
### Advanced Extension features
@ -519,8 +495,9 @@ multisrc
│   │   │   └── ic_launcher.png
│   │   ├── mipmap-xxhdpi
│   │   │   └── ic_launcher.png
│   │   └── mipmap-xxxhdpi
│   │      └── ic_launcher.png
│   │   ├── mipmap-xxxhdpi
│   │   │   └── ic_launcher.png
│   │   └── web_hi_res_512.png
│   └── <sourcepkg>
│   ├── additional.gradle
│   ├── AndroidManifest.xml
@ -533,8 +510,9 @@ multisrc
│   │   │   └── ic_launcher.png
│   │   ├── mipmap-xxhdpi
│   │   │   └── ic_launcher.png
│   │   └── mipmap-xxxhdpi
│   │      └── ic_launcher.png
│   │   ├── mipmap-xxxhdpi
│   │   │   └── ic_launcher.png
│   │   └── web_hi_res_512.png
│   └── src
│   └── <SourceName>.kt
└── src
@ -761,9 +739,7 @@ When you feel confident about your changes, submit a new Pull Request so your co
If you are more comfortable about using Git GUI-based tools, you can refer to [this guide](https://learntodroid.com/how-to-use-git-and-github-in-android-studio/) about the Git integration inside Android Studio, specifically the "How to Contribute to an to Existing Git Repository in Android Studio" section of the guide.
> [!IMPORTANT]
> Make sure you have generated the extension icon using the linked Icon Generator tool in the [Tools](#tools)
> section. The icon **must follow the pattern** adopted by all other extensions: a square with rounded
> corners. Make sure to remove the generated `web_hi_res_512.png`.
> Make sure you have generated the extension icon using the linked Icon Generator tool in the [Tools](#tools) section. The icon **must follow the pattern** adopted by all other extensions: a square with rounded corners.
Please **do test your changes by compiling it through Android Studio** before submitting it. Obvious untested PRs will not be merged, such as ones created with the GitHub web interface. Also make sure to follow the PR checklist available in the PR body field when creating a new PR. As a reference, you can find it below.

View File

@ -1,6 +1,3 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlinx-serialization'
apply plugin: 'org.jmailen.kotlinter'
android {
@ -28,9 +25,7 @@ android {
applicationIdSuffix pkgNameSuffix
versionCode extVersionCode
versionName project.ext.properties.getOrDefault("libVersion", "1.4") + ".$extVersionCode"
base {
archivesName = "tachiyomi-$pkgNameSuffix-v$versionName"
}
setProperty("archivesBaseName", "tachiyomi-$pkgNameSuffix-v$versionName")
def readmes = project.projectDir.listFiles({ File file ->
file.name == "README.md" || file.name == "CHANGELOG.md"
} as FileFilter)
@ -76,7 +71,6 @@ android {
renderScript false
resValues false
shaders false
buildConfig true
}
compileOptions {

View File

@ -9,7 +9,7 @@ android {
minSdk = AndroidConfig.minSdk
}
namespace = "eu.kanade.tachiyomi.extension.core"
namespace = "eu.kanade.tachiyomi.extension"
@Suppress("UnstableApiUsage")
sourceSets {

View File

@ -21,5 +21,3 @@ org.gradle.caching=true
# Enable AndroidX dependencies
android.useAndroidX=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false

View File

@ -4,7 +4,7 @@ coroutines_version = "1.6.4"
serialization_version = "1.4.0"
[libraries]
gradle-agp = { module = "com.android.tools.build:gradle", version = "8.2.1" }
gradle-agp = { module = "com.android.tools.build:gradle", version = "7.4.2" }
gradle-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin_version" }
gradle-serialization = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlin_version" }
gradle-kotlinter = { module = "org.jmailen.gradle:kotlinter-gradle", version = "3.13.0" }

View File

@ -1,22 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity
android:name="eu.kanade.tachiyomi.multisrc.a3manga.A3MangaUrlActivity"
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:host="${SOURCEHOST}" />
<data android:host="*.${SOURCEHOST}" />
<data android:pathPattern="/truyen-tranh/..*"
android:scheme="${SOURCESCHEME}" />
</intent-filter>
</activity>
</application>
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity
android:name="eu.kanade.tachiyomi.multisrc.a3manga.A3MangaUrlActivity"
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:host="${SOURCEHOST}" />
<data android:host="*.${SOURCEHOST}" />
<data android:pathPattern="/truyen-tranh/..*"
android:scheme="${SOURCESCHEME}" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.extension.vi.ngonphong
import eu.kanade.tachiyomi.multisrc.a3manga.A3Manga
class NgonPhong : A3Manga("Ngôn Phong", "https://www.ngonphong.com", "vi") {
override val id: Long = 7268977637085631557
}
package eu.kanade.tachiyomi.extension.vi.ngonphong
import eu.kanade.tachiyomi.multisrc.a3manga.A3Manga
class NgonPhong : A3Manga("Ngôn Phong", "https://www.ngonphong.com", "vi") {
override val id: Long = 7268977637085631557
}

View File

@ -1,68 +0,0 @@
package eu.kanade.tachiyomi.extension.tr.mangatr
import android.webkit.CookieManager
import eu.kanade.tachiyomi.network.GET
import okhttp3.Cookie
import okhttp3.HttpUrl
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
// Taken from src/all/akuma.
class DDoSGuardInterceptor(private val client: OkHttpClient) : Interceptor {
private val cookieManager by lazy { CookieManager.getInstance() }
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
val response = chain.proceed(originalRequest)
// Check if DDos-GUARD is on
if (response.code !in ERROR_CODES || response.header("Server") !in SERVER_CHECK) {
return response
}
val cookies = cookieManager.getCookie(originalRequest.url.toString())
val oldCookie = if (cookies != null && cookies.isNotEmpty()) {
cookies.split(";").mapNotNull { Cookie.parse(originalRequest.url, it) }
} else {
emptyList()
}
val ddg2Cookie = oldCookie.firstOrNull { it.name == "__ddg2_" }
if (!ddg2Cookie?.value.isNullOrEmpty()) {
return response
}
response.close()
val newCookie = getNewCookie(originalRequest.url)
?: return chain.proceed(originalRequest)
val newCookieHeader = (oldCookie + newCookie)
.joinToString("; ") { "${it.name}=${it.value}" }
val modifiedRequest = originalRequest.newBuilder()
.header("cookie", newCookieHeader)
.build()
return chain.proceed(modifiedRequest)
}
private fun getNewCookie(url: HttpUrl): Cookie? {
val wellKnown = client.newCall(GET(wellKnownUrl))
.execute().body.string()
.substringAfter("'", "")
.substringBefore("'", "")
val checkUrl = "${url.scheme}://${url.host + wellKnown}"
val response = client.newCall(GET(checkUrl)).execute()
return response.header("set-cookie")?.let {
Cookie.parse(url, it)
}
}
companion object {
private const val wellKnownUrl = "https://check.ddos-guard.net/check.js"
private val ERROR_CODES = listOf(403)
private val SERVER_CHECK = listOf("ddos-guard")
}
}

View File

@ -19,15 +19,6 @@ class MangaTR : FMReader("Manga-TR", "https://manga-tr.com", "tr") {
override fun headersBuilder() = super.headersBuilder()
.add("Accept-Language", "en-US,en;q=0.5")
override val client by lazy {
super.client.newBuilder()
.addInterceptor(DDoSGuardInterceptor(super.client))
.build()
}
override val requestPath = "manga-list-sayfala.html"
// ============================== Popular ===============================
override fun popularMangaNextPageSelector() = "div.btn-group:not(div.btn-block) button.btn-info"
// =============================== Search ===============================

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,9 +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
override fun searchPage(page: Int): String = if (page == 1) "" else "page/$page/"
}

View File

@ -4,7 +4,6 @@ import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
import eu.kanade.tachiyomi.source.model.SManga
import okhttp3.CacheControl
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request
import org.jsoup.nodes.Document
@ -24,47 +23,17 @@ class MangasNoSekai : Madara(
override val useNewChapterEndpoint = true
override val mangaSubString = "manganews"
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/${searchPage(page)}?s=&post_type=wp-manga&m_orderby=views", headers)
override fun popularMangaRequest(page: Int): Request {
return GET(
url = "$baseUrl/$mangaSubString/${searchPage(page)}?m_orderby=views",
headers = headers,
cache = CacheControl.FORCE_NETWORK,
)
}
override fun popularMangaSelector() = searchMangaSelector()
override fun popularMangaSelector() = "div.page-listing-item > div.row > div"
override fun popularMangaFromElement(element: Element) = searchMangaFromElement(element)
override val popularMangaUrlSelector = "a[href]"
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/${searchPage(page)}?s=&post_type=wp-manga&m_orderby=latest", headers)
override fun popularMangaFromElement(element: Element): SManga {
val manga = SManga.create()
override fun latestUpdatesSelector() = searchMangaSelector()
with(element) {
select(popularMangaUrlSelector).first()?.let {
manga.setUrlWithoutDomain(it.attr("abs:href"))
}
select("figcaption").first()?.let {
manga.title = it.text()
}
select("img").first()?.let {
manga.thumbnail_url = imageFromElement(it)
}
}
return manga
}
override fun latestUpdatesRequest(page: Int): Request {
return GET(
url = "$baseUrl/$mangaSubString/${searchPage(page)}?m_orderby=latest",
headers = headers,
cache = CacheControl.FORCE_NETWORK,
)
}
override fun latestUpdatesFromElement(element: Element) = searchMangaFromElement(element)
override fun searchPage(page: Int): String {
return if (page > 1) "page/$page/" else ""
@ -143,14 +112,4 @@ class MangasNoSekai : Madara(
return manga
}
override val orderByFilterOptionsValues: Array<String> = arrayOf(
"",
"latest2",
"alphabet",
"rating",
"trending",
"views2",
"new-manga",
)
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

View File

@ -1,24 +0,0 @@
package eu.kanade.tachiyomi.extension.pt.nexoscans
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import okhttp3.OkHttpClient
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
class NexoScans : Madara(
"Nexo Scans",
"https://nexoscans.com",
"pt-BR",
SimpleDateFormat("dd/MM/yyyy", Locale.US),
) {
override val client: OkHttpClient = super.client.newBuilder()
.rateLimit(1, 2, TimeUnit.SECONDS)
.build()
override val useNewChapterEndpoint = true
override val chapterUrlSelector = "a:not(div.chapter-thumbnail a)"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 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: 39 KiB

View File

@ -1,19 +1,19 @@
package eu.kanade.tachiyomi.extension.es.rightdarkscan
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import java.text.SimpleDateFormat
import java.util.Locale
class RightdarkScan : Madara(
"Rightdark Scan",
"https://rightdark-scan.com",
"es",
SimpleDateFormat("MMMM dd, yyyy", Locale("es")),
) {
override val client = super.client.newBuilder()
.rateLimit(2, 1)
.build()
override val useNewChapterEndpoint = true
}
package eu.kanade.tachiyomi.extension.es.rightdarkscan
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import java.text.SimpleDateFormat
import java.util.Locale
class RightdarkScan : Madara(
"Rightdark Scan",
"https://rightdark-scan.com",
"es",
SimpleDateFormat("MMMM dd, yyyy", Locale("es")),
) {
override val client = super.client.newBuilder()
.rateLimit(2, 1)
.build()
override val useNewChapterEndpoint = true
}

View File

@ -1,3 +0,0 @@
dependencies {
implementation(project(":lib-synchrony"))
}

View File

@ -1,28 +1,11 @@
package eu.kanade.tachiyomi.extension.id.shinigami
import android.app.Application
import android.content.SharedPreferences
import android.util.Base64
import android.widget.Toast
import androidx.preference.EditTextPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES
import eu.kanade.tachiyomi.lib.synchrony.Deobfuscator
import eu.kanade.tachiyomi.multisrc.madara.Madara
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import eu.kanade.tachiyomi.source.model.SChapter
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import okhttp3.Headers
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
import java.util.concurrent.TimeUnit
class Shinigami : Madara("Shinigami", "https://shinigamitoon.com", "id") {
@ -33,91 +16,15 @@ class Shinigami : Madara("Shinigami", "https://shinigamitoon.com", "id") {
override fun searchPage(page: Int): String = if (page == 1) "" else "page/$page/"
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
private val encodedString = "AAA AaAAAAH QAAAB0 AAAAcA AAAHMAA AA6AAA ALwAAAC8AA " + "AB0AAAAYQA AAGM AAADoAAAAaQAAAH kAAABvAA AAbQAAA GkAAABvAAAA cgAAAGcAAAAuAAA AZwAAAGk " + "AAAB0AAAA aAAAAHUAA ABiAAAALgAAAGkAA ABvAAAAL wAAAHUAAABzA AAAZQAAAHIAAAAtA AAAYQAAAGcA " + "AABlyAtAAAbgA AAHQAAAB6AAAA LwAAAHUAAA BcAAAAZQ AAAHIAAAAtAAA AYQAAAGcAAABl AAAAbgAA AHQAAAB6AAAALgAAAG" + " oAhAntUAABzAA AAbwAAAG4="
private val tachiUaUrl = Base64.decode(encodedString.replace("\\s".toRegex(), "").replace("DoA", "BoA").replace("GoAhAntU", "GoA").replace("BlyAt", "BlA").replace("BcA", "BzA"), Base64.DEFAULT).toString(Charsets.UTF_32).replace("z", "s")
private var secChUaMP: List<String>? = null
private var userAgent: String? = null
private var checkedUa = false
private val uaIntercept = object : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val customUa = preferences.getString(PREF_KEY_CUSTOM_UA, "")
try {
if (customUa!!.isNotBlank()) userAgent = customUa
if (userAgent.isNullOrBlank() && checkedUa.not()) {
val uaResponse = chain.proceed(GET(tachiUaUrl))
if (uaResponse.isSuccessful) {
val parseTachiUa = uaResponse.use { json.decodeFromString<TachiUaResponse>(it.body.string()) }
var listUserAgentString = parseTachiUa.desktop + parseTachiUa.mobile
listUserAgentString = listUserAgentString!!.filter {
listOf("windows", "android").any { filter ->
it.contains(filter, ignoreCase = true)
}
}
userAgent = listUserAgentString!!.random()
checkedUa = true
}
uaResponse.close()
}
if (userAgent.isNullOrBlank().not()) {
secChUaMP = if (userAgent!!.contains("Windows")) {
listOf("?0", "Windows")
} else {
listOf("?1", "Android")
}
val newRequest = chain.request().newBuilder()
.header("User-Agent", userAgent!!.trim())
.header("Sec-CH-UA-Mobile", secChUaMP!![0])
.header("Sec-CH-UA-Platform", secChUaMP!![1])
.removeHeader("X-Requested-With")
.build()
return chain.proceed(newRequest)
}
return chain.proceed(chain.request())
} catch (e: Exception) {
throw IOException(e.message)
}
}
}
@Serializable
data class TachiUaResponse(
val desktop: List<String> = emptyList(),
val mobile: List<String> = emptyList(),
)
// disable random ua in ext setting from multisrc (.setRandomUserAgent)
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.addInterceptor(uaIntercept)
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
override val client: OkHttpClient = super.client.newBuilder()
.rateLimit(4, 1, TimeUnit.SECONDS)
.build()
override fun headersBuilder(): Headers.Builder {
val builder = super.headersBuilder()
.add("Sec-Fetch-Dest", "document")
.add("Sec-Fetch-Mode", "navigate")
.add("Sec-Fetch-Site", "same-origin")
.add("Upgrade-Insecure-Requests", "1")
.add("X-Requested-With", "") // added for webview, and removed in interceptor for normal use
// used to flush tachi custom ua in webview and use system ua instead
if (userAgent.isNullOrBlank()) builder.removeAll("User-Agent")
return builder
}
override fun headersBuilder(): Headers.Builder = super.headersBuilder()
.add("Sec-Fetch-Dest", "document")
.add("Sec-Fetch-Mode", "navigate")
.add("Sec-Fetch-Site", "same-origin")
.add("Upgrade-Insecure-Requests", "1")
override val mangaSubString = "semua-series"
@ -136,76 +43,4 @@ class Shinigami : Madara("Shinigami", "https://shinigamitoon.com", "id") {
setUrlWithoutDomain(fixedUrl)
}
// Page list
@Serializable
data class CDT(val ct: String, val s: String)
override fun pageListParse(document: Document): List<Page> {
val script = document.selectFirst("script:containsData(chapter_data)")?.data()
?: throw Exception("chapter_data script not found")
val deobfuscated = Deobfuscator.deobfuscateScript(script)
?: throw Exception("Unable to deobfuscate chapter_data script")
val postId = script.substringAfter("var post_id = '").substringBefore("'")
val chapterData = json.decodeFromString<CDT>(
script.substringAfter("var chapter_data = '").substringBefore("'"),
)
val keyMatch = KEY_REGEX.find(deobfuscated)!!.groupValues
val key = postId + keyMatch[1] + postId + keyMatch[2] + postId
val salt = chapterData.s.decodeHex()
val unsaltedCiphertext = Base64.decode(chapterData.ct, Base64.DEFAULT)
val ciphertext = SALTED + salt + unsaltedCiphertext
val decrypted = CryptoAES.decrypt(Base64.encodeToString(ciphertext, Base64.DEFAULT), key)
val data = json.decodeFromString<List<String>>(decrypted)
return data.mapIndexed { idx, it ->
Page(idx, document.location(), it)
}
}
// https://stackoverflow.com/a/66614516
private fun String.decodeHex(): ByteArray {
check(length % 2 == 0) { "Must have an even length" }
return chunked(2)
.map { it.toInt(16).toByte() }
.toByteArray()
}
// remove random ua in setting ext from multisrc and use custom one
override fun setupPreferenceScreen(screen: PreferenceScreen) {
val prefCustomUserAgent = EditTextPreference(screen.context).apply {
key = PREF_KEY_CUSTOM_UA
title = TITLE_CUSTOM_UA
summary = (preferences.getString(PREF_KEY_CUSTOM_UA, "")!!.trim() + SUMMARY_STRING_CUSTOM_UA).trim()
setOnPreferenceChangeListener { _, newValue ->
val customUa = newValue as String
preferences.edit().putString(PREF_KEY_CUSTOM_UA, customUa).apply()
if (customUa.isNullOrBlank()) {
Toast.makeText(screen.context, RESTART_APP_STRING, Toast.LENGTH_LONG).show()
} else {
userAgent = null
}
summary = (customUa.trim() + SUMMARY_STRING2_CUSTOM_UA).trim()
true
}
}
screen.addPreference(prefCustomUserAgent)
}
companion object {
const val TITLE_CUSTOM_UA = "Custom User-Agent"
const val PREF_KEY_CUSTOM_UA = "pref_key_custom_ua"
const val SUMMARY_STRING_CUSTOM_UA = "\n\nBiarkan kosong untuk menggunakan User-Agent secara random"
const val SUMMARY_STRING2_CUSTOM_UA = "\n\nKosongkan untuk menggunakan User-Agent secara random"
const val RESTART_APP_STRING = "Restart Tachiyomi untuk menggunakan pengaturan baru."
private val KEY_REGEX by lazy { Regex("""post_id\s+\+\s+'(.*?)'\s+\+\s+post_id\s+\+\s+'(.*?)'\s+\+\s+post_id""") }
}
}

View File

@ -1,15 +0,0 @@
package eu.kanade.tachiyomi.extension.es.tenkaiscan
import eu.kanade.tachiyomi.multisrc.madara.Madara
import java.text.SimpleDateFormat
import java.util.Locale
class TenkaiScan : Madara(
"TenkaiScan",
"https://tenkaiscan.net",
"es",
dateFormat = SimpleDateFormat("dd 'de' MMMM 'de' yyyy", Locale("es")),
) {
override val versionId = 2
override val useNewChapterEndpoint = true
override val mangaDetailsSelectorStatus = "div.post-content_item:contains(Status) > div.summary-content"
}

View File

@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.extension.es.carteldemanhwas
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import org.jsoup.nodes.Element
import java.text.SimpleDateFormat
import java.util.Locale
@ -15,13 +14,6 @@ class CarteldeManhwas : MangaThemesia(
override val hasProjectPage = true
override val projectPageString = "/proyectos"
override fun Element.imgAttr(): String = when {
hasAttr("data-lazy-src") -> attr("abs:data-lazy-src")
hasAttr("data-cfsrc") -> attr("abs:data-cfsrc")
hasAttr("data-src") -> attr("abs:data-src")
else -> attr("abs:src")
}
override fun searchMangaSelector() = ".utao .uta .imgu:not(:has(span.novelabel)), " +
".listupd .bs .bsx:not(:has(span.novelabel)), " +
".listo .bs .bsx:not(:has(span.novelabel))"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

View File

@ -1,12 +0,0 @@
package eu.kanade.tachiyomi.extension.id.shirakami
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import java.text.SimpleDateFormat
import java.util.Locale
class Shirakami : MangaThemesia(
"Shirakami",
"https://shirakami.xyz",
"id",
dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale("id")),
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

@ -0,0 +1,12 @@
package eu.kanade.tachiyomi.extension.es.tenkaiscan
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
import java.text.SimpleDateFormat
import java.util.Locale
class TenkaiScan : MangaThemesia(
"TenkaiScan",
"https://tenkaiscan.net",
"es",
dateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale("en")),
)

View File

@ -1,22 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity
android:name="eu.kanade.tachiyomi.multisrc.mymangacms.MyMangaCMSUrlActivity"
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:host="${SOURCEHOST}"
android:pathPattern="/..*"
android:scheme="${SOURCESCHEME}" />
</intent-filter>
</activity>
</application>
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity
android:name="eu.kanade.tachiyomi.multisrc.mymangacms.MyMangaCMSUrlActivity"
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:host="${SOURCEHOST}"
android:pathPattern="/..*"
android:scheme="${SOURCESCHEME}" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -1,10 +1,10 @@
package eu.kanade.tachiyomi.extension.id.komikindoinfo
import eu.kanade.tachiyomi.multisrc.zmanga.ZManga
import java.text.SimpleDateFormat
import java.util.Locale
class KomikIndoInfo : ZManga("KomikIndo.info", "http://komikindo.info", "id", dateFormat = SimpleDateFormat("MMM d, yyyy", Locale("id"))) {
override val hasProjectPage = true
}
package eu.kanade.tachiyomi.extension.id.komikindoinfo
import eu.kanade.tachiyomi.multisrc.zmanga.ZManga
import java.text.SimpleDateFormat
import java.util.Locale
class KomikIndoInfo : ZManga("KomikIndo.info", "http://komikindo.info", "id", dateFormat = SimpleDateFormat("MMM d, yyyy", Locale("id"))) {
override val hasProjectPage = true
}

View File

@ -56,13 +56,13 @@ open class A3Manga(
override fun popularMangaNextPageSelector() = "li.next:not(.disabled)"
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException()
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException("Not used")
override fun latestUpdatesSelector() = throw UnsupportedOperationException()
override fun latestUpdatesSelector() = throw UnsupportedOperationException("Not used")
override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException()
override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException("Not used")
override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException()
override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException("Not used")
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
return when {
@ -92,11 +92,11 @@ open class A3Manga(
.build(),
)
override fun searchMangaSelector(): String = throw UnsupportedOperationException()
override fun searchMangaSelector(): String = throw UnsupportedOperationException("Not used")
override fun searchMangaFromElement(element: Element): SManga = throw UnsupportedOperationException()
override fun searchMangaFromElement(element: Element): SManga = throw UnsupportedOperationException("Not used")
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException()
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException("Not used")
override fun searchMangaParse(response: Response): MangasPage {
val dto = response.parseAs<SearchResponseDto>()
@ -213,7 +213,7 @@ open class A3Manga(
}
}
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used")
private inline fun <reified T> Response.parseAs(): T {
return json.decodeFromString(body.string())

View File

@ -134,35 +134,35 @@ abstract class BakkinReaderX(
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun popularMangaRequest(page: Int) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun latestUpdatesRequest(page: Int) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun mangaDetailsRequest(manga: SManga) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun searchMangaParse(response: Response) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun popularMangaParse(response: Response) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun latestUpdatesParse(response: Response) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun mangaDetailsParse(response: Response) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun chapterListParse(response: Response) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun pageListParse(response: Response) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun imageUrlParse(response: Response) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
}

View File

@ -40,19 +40,19 @@ open class ComicGamma(
thumbnail_url = element.selectFirst(Evaluator.Tag("img"))!!.absUrl("src")
}
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException()
override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException()
override fun latestUpdatesSelector() = throw UnsupportedOperationException()
override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException()
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException("Not used.")
override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException("Not used.")
override fun latestUpdatesSelector() = throw UnsupportedOperationException("Not used.")
override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException("Not used.")
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> =
fetchPopularManga(page).map { p -> MangasPage(p.mangas.filter { it.title.contains(query) }, false) }
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException()
override fun searchMangaSelector() = throw UnsupportedOperationException()
override fun searchMangaFromElement(element: Element) = throw UnsupportedOperationException()
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException("Not used.")
override fun searchMangaSelector() = throw UnsupportedOperationException("Not used.")
override fun searchMangaFromElement(element: Element) = throw UnsupportedOperationException("Not used.")
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used.")
override fun pageListParse(document: Document) =
document.select("#content > div[data-ptimg]").mapIndexed { i, e ->
@ -91,7 +91,7 @@ open class ComicGamma(
override fun pageListRequest(chapter: SChapter) =
GET(baseUrl + chapter.url.toNewChapterUrl(), headers)
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used.")
companion object {
internal fun SimpleDateFormat.parseJST(date: String) = parse(date)?.apply {

View File

@ -188,15 +188,15 @@ open class EroMuse(override val name: String, override val baseUrl: String) : Ht
override fun fetchPopularManga(page: Int): Observable<MangasPage> = fetchManga("$baseUrl/comics/album/Various-Authors", page, "")
override fun popularMangaRequest(page: Int): Request = throw UnsupportedOperationException()
override fun popularMangaParse(response: Response): MangasPage = throw UnsupportedOperationException()
override fun popularMangaRequest(page: Int): Request = throw UnsupportedOperationException("Not used")
override fun popularMangaParse(response: Response): MangasPage = throw UnsupportedOperationException("Not used")
// Latest
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> = fetchManga("$baseUrl/comics/album/Various-Authors?sort=date", page, "date")
override fun latestUpdatesRequest(page: Int): Request = throw UnsupportedOperationException()
override fun latestUpdatesParse(response: Response): MangasPage = throw UnsupportedOperationException()
override fun latestUpdatesRequest(page: Int): Request = throw UnsupportedOperationException("Not used")
override fun latestUpdatesParse(response: Response): MangasPage = throw UnsupportedOperationException("Not used")
// Search
@ -228,8 +228,8 @@ open class EroMuse(override val name: String, override val baseUrl: String) : Ht
.map { response -> parseManga(response.asJsoup()) }
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = throw UnsupportedOperationException()
override fun searchMangaParse(response: Response): MangasPage = throw UnsupportedOperationException()
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = throw UnsupportedOperationException("Not used")
override fun searchMangaParse(response: Response): MangasPage = throw UnsupportedOperationException("Not used")
// Details
@ -332,7 +332,7 @@ open class EroMuse(override val name: String, override val baseUrl: String) : Ht
return parsePages(response.asJsoup())
}
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException()
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Not used")
// Filters

View File

@ -190,7 +190,7 @@ abstract class FansubsCat(
override fun pageListParse(response: Response): List<Page> = parsePageListFromJson(response)
override fun imageUrlParse(response: Response): String =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used")
// Filter
override fun getFilterList() = FilterList(

View File

@ -263,7 +263,7 @@ abstract class FlixScans(
}
}
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Not Used")
protected inline fun <reified T> Response.parseAs(): T =
use { body.string() }.let(json::decodeFromString)

View File

@ -333,7 +333,7 @@ abstract class FMReader(
}
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
private class TextField(name: String, val key: String) : Filter.Text(name)
private class Status : Filter.Select<String>("Status", arrayOf("Any", "Completed", "Ongoing"))

View File

@ -14,7 +14,7 @@ class FMReaderGenerator : ThemeSourceGenerator {
override val sources = listOf(
SingleLang("Epik Manga", "https://www.epikmanga.com", "tr"),
SingleLang("KissLove", "https://klz9.com", "ja", isNsfw = true, overrideVersionCode = 4),
SingleLang("Manga-TR", "https://manga-tr.com", "tr", className = "MangaTR", overrideVersionCode = 3),
SingleLang("Manga-TR", "https://manga-tr.com", "tr", className = "MangaTR", overrideVersionCode = 2),
SingleLang("ManhuaRock", "https://manhuarock.net", "vi", overrideVersionCode = 1),
SingleLang("Say Truyen", "https://saytruyenvip.com", "vi", overrideVersionCode = 3),
SingleLang("WeLoveManga", "https://weloma.art", "ja", pkgName = "rawlh", isNsfw = true, overrideVersionCode = 5),

View File

@ -271,7 +271,7 @@ abstract class FoolSlide(
}
}
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used")
protected val preferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)!!

View File

@ -255,7 +255,7 @@ abstract class GroupLe(
}
override fun chapterFromElement(element: Element): SChapter {
throw UnsupportedOperationException()
throw Exception("Not used")
}
override fun prepareNewChapter(chapter: SChapter, manga: SManga) {
@ -288,11 +288,6 @@ abstract class GroupLe(
var readerMark = "rm_h.readerDoInit(["
// allhentai necessary
if (!html.contains(readerMark)) {
readerMark = "rm_h.readerInit( 0,["
}
if (!html.contains(readerMark)) {
if (document.select(".input-lg").isNotEmpty() || (document.select(".user-avatar").isNullOrEmpty() && document.select("img.logo").first()?.attr("title")?.contains("Allhentai") == true)) {
throw Exception("Для просмотра контента необходима авторизация через WebView\uD83C\uDF0E")

View File

@ -9,7 +9,7 @@ class GroupLeGenerator : ThemeSourceGenerator {
override val themeClass = "GroupLe"
override val baseVersionCode = 22
override val baseVersionCode = 21
override val sources = listOf(
SingleLang("ReadManga", "https://readmanga.live", "ru", overrideVersionCode = 46),

View File

@ -455,7 +455,7 @@ abstract class Guya(
// ----------------- Things we aren't supporting -----------------
override fun mangaDetailsParse(response: Response): SManga {
throw UnsupportedOperationException()
throw UnsupportedOperationException("Unused")
}
override fun chapterListParse(response: Response): List<SChapter> {
@ -467,11 +467,11 @@ abstract class Guya(
}
override fun searchMangaParse(response: Response): MangasPage {
throw UnsupportedOperationException()
throw UnsupportedOperationException("Unused.")
}
override fun imageUrlParse(response: Response): String {
throw UnsupportedOperationException()
throw UnsupportedOperationException("Unused.")
}
companion object {

View File

@ -274,7 +274,7 @@ abstract class HentaiHand(
Page(index, "", imgUrl)
}
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException()
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Not used")
// Authorization

View File

@ -123,7 +123,7 @@ abstract class LibGroup(
.build()
// Latest
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException() // popularMangaRequest()
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException("Not used") // popularMangaRequest()
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> {
if (csrfToken.isEmpty()) {
return client.newCall(popularMangaRequest(page))

View File

@ -285,7 +285,7 @@ abstract class Madara(
else -> arrayOf("Completed", "Ongoing", "Canceled", "On Hold")
}
protected open val statusFilterOptionsValues: Array<String> = arrayOf(
protected val statusFilterOptionsValues: Array<String> = arrayOf(
"end",
"on-going",
"canceled",
@ -318,7 +318,7 @@ abstract class Madara(
)
}
protected open val orderByFilterOptionsValues: Array<String> = arrayOf(
protected val orderByFilterOptionsValues: Array<String> = arrayOf(
"",
"latest",
"alphabet",

View File

@ -65,6 +65,7 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("Cat300", "https://cat300.com", "th", isNsfw = true, className = "Cat300", overrideVersionCode = 1),
SingleLang("CatOnHeadTranslations", "https://catonhead.com", "en", overrideVersionCode = 2),
SingleLang("Cerise Scan", "https://cerisescan.com", "pt-BR", pkgName = "cerisescans", isNsfw = true, overrideVersionCode = 7),
SingleLang("Çizgi Roman Arşivi", "https://cizgiromanarsivi.com", "tr", className = "CizgiRomanArsivi"),
SingleLang("Clover Manga", "https://clover-manga.com", "tr", overrideVersionCode = 2),
SingleLang("Coco Rip", "https://cocorip.net", "es"),
SingleLang("Coffee Manga", "https://coffeemanga.io", "en", isNsfw = false, overrideVersionCode = 2),
@ -192,7 +193,7 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("Lolicon", "https://lolicon.mobi", "en", isNsfw = true, overrideVersionCode = 2),
SingleLang("Lord Manga", "https://lordmanga.com", "en"),
SingleLang("Luffy Manga", "https://luffymanga.com", "en", isNsfw = false),
SingleLang("LuxManga", "https://luxmanga.net", "en", isNsfw = true, overrideVersionCode = 1),
SingleLang("LuxManga", "https://luxmanga.com", "en"),
SingleLang("MadaraDex", "https://madaradex.org", "en", isNsfw = true, overrideVersionCode = 1),
SingleLang("Maid Scan", "https://maidscan.com.br", "pt-BR"),
SingleLang("Manga 18h", "https://manga18h.com", "en", isNsfw = true),
@ -213,22 +214,23 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("Manga Lord", "https://mangalord.com", "en", overrideVersionCode = 1),
SingleLang("Manga Mammy", "https://mangamammy.ru", "ru", isNsfw = true),
SingleLang("Manga Mitsu", "https://mangamitsu.com", "en", isNsfw = true, overrideVersionCode = 2),
SingleLang("Mangá Nanquim", "https://mangananquim.com", "pt-BR", className = "MangaNanquim"),
SingleLang("Manga Nerds", "https://manganerds.com", "en", isNsfw = false),
SingleLang("Manga One Love", "https://mangaonelove.site/", "ru", isNsfw = true),
SingleLang("Manga Online Team", "https://mangaonlineteam.com", "en"),
SingleLang("Manga Queen", "https://mangaqueen.net", "en"),
SingleLang("Manga Queen.com", "https://mangaqueen.com", "en", isNsfw = true, className = "MangaQueenCom"),
SingleLang("Manga Queen.online (unoriginal)", "https://mangaqueen.online", "en", isNsfw = true, className = "MangaQueenOnline"),
SingleLang("Manga Queen", "https://mangaqueen.net", "en"),
SingleLang("Manga Read", "https://mangaread.co", "en", overrideVersionCode = 1),
SingleLang("Manga Rock Team", "https://mangarockteam.com", "en", overrideVersionCode = 1),
SingleLang("Manga Rock.team (unoriginal)", "https://mangarock.team", "en", isNsfw = false, className = "MangaRockTeamUnoriginal"),
SingleLang("Manga Rocky", "https://mangarocky.com", "en", overrideVersionCode = 1),
SingleLang("Manga Rose", "https://mangarose.net", "ar"),
SingleLang("Manga Şehri", "https://manga-sehri.com", "tr", className = "MangaSehri", isNsfw = true, overrideVersionCode = 1),
SingleLang("Manga Starz", "https://mangastarz.org", "ar", overrideVersionCode = 5),
SingleLang("Manga Too", "https://mangatoo.com", "en", overrideVersionCode = 1),
SingleLang("Manga Tx.gg (unoriginal)", "https://mangatx.gg", "en", isNsfw = false, className = "MangaTxGg"),
SingleLang("Manga Weebs", "https://mangaweebs.in", "en", overrideVersionCode = 8),
SingleLang("Manga Şehri", "https://manga-sehri.com", "tr", className = "MangaSehri", isNsfw = true, overrideVersionCode = 1),
SingleLang("Manga-1001.com", "https://manga-1001.com", "en", isNsfw = false, className = "MangaDash1001Com"),
SingleLang("Manga-fast.com", "https://manga-fast.com", "en", className = "Mangafastcom", overrideVersionCode = 3),
SingleLang("Manga-Raw.info (unoriginal)", "https://manga-raw.info", "en", isNsfw = true, className = "MangaRawInfo"),
@ -242,8 +244,8 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("MangaBaz", "https://mangabaz.net", "en"),
SingleLang("MangaBob", "https://mangabob.com", "en", overrideVersionCode = 1),
SingleLang("MangaCC", "https://mangacc.com", "en"),
SingleLang("MangaClash", "https://mangaclash.com", "en", overrideVersionCode = 3),
SingleLang("MangaClash.tv (unoriginal)", "https://mangaclash.tv", "en", isNsfw = true, className = "MangaClashTv"),
SingleLang("MangaClash", "https://mangaclash.com", "en", overrideVersionCode = 3),
SingleLang("MangaCrazy", "https://mangacrazy.net", "all", isNsfw = true),
SingleLang("MangaCultivator", "https://mangacultivator.com", "en", overrideVersionCode = 2),
SingleLang("MangaCV", "https://mangacv.com", "en", isNsfw = true),
@ -285,7 +287,7 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("MangaRosie", "https://mangarosie.in", "en", isNsfw = true),
SingleLang("MangaRuby.com", "https://mangaruby.com", "en", isNsfw = true, className = "MangaRubyCom"),
SingleLang("Mangaryu", "https://mangaryu.com", "en", isNsfw = true),
SingleLang("Mangas No Sekai", "https://mangasnosekai.com", "es", overrideVersionCode = 2),
SingleLang("Mangas No Sekai", "https://mangasnosekai.com", "es", overrideVersionCode = 1),
SingleLang("Mangas Origines", "https://mangas-origines.xyz", "fr", isNsfw = true, overrideVersionCode = 4),
SingleLang("Mangas-Origines.fr", "https://mangas-origines.fr", "fr", className = "MangasOriginesFr"),
SingleLang("MangaSco", "https://manhwasco.net", "en", overrideVersionCode = 2),
@ -305,7 +307,6 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("Mangaxico", "https://mangaxico.com", "es", isNsfw = true),
SingleLang("MangaXP", "https://mangaxp.com", "en", overrideVersionCode = 1),
SingleLang("MangaYami", "https://www.mangayami.club", "en", overrideVersionCode = 2),
SingleLang("Mangá Nanquim", "https://mangananquim.com", "pt-BR", className = "MangaNanquim"),
SingleLang("Manhastro", "https://manhastro.com", "pt-BR"),
SingleLang("Manhatic", "https://manhatic.com", "ar", isNsfw = true),
SingleLang("Manhua ES", "https://manhuaes.com", "en", overrideVersionCode = 6),
@ -318,12 +319,12 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("ManhuaBox", "https://manhuabox.net", "en", overrideVersionCode = 2),
SingleLang("ManhuaChill", "https://manhuachill.com", "en"),
SingleLang("ManhuaDex", "https://manhuadex.com", "en", isNsfw = false),
SingleLang("ManhuaFast", "https://manhuafast.com", "en", overrideVersionCode = 3),
SingleLang("ManhuaFast.net (unoriginal)", "https://manhuafast.net", "en", isNsfw = false, className = "ManhuaFastNet"),
SingleLang("ManhuaFast", "https://manhuafast.com", "en", overrideVersionCode = 3),
SingleLang("Manhuaga", "https://manhuaga.com", "en", overrideVersionCode = 2),
SingleLang("ManhuaHot", "https://manhuahot.com", "en"),
SingleLang("ManhuaManhwa", "https://manhuamanhwa.com", "en", isNsfw = true),
SingleLang("ManhuaManhwa.online", "https://manhuamanhwa.online", "en", isNsfw = false, className = "ManhuaManhwaOnline"),
SingleLang("ManhuaManhwa", "https://manhuamanhwa.com", "en", isNsfw = true),
SingleLang("ManhuaScan.info (unoriginal)", "https://manhuascan.info", "en", isNsfw = true, className = "ManhuaScanInfo"),
SingleLang("ManhuaUS", "https://manhuaus.com", "en", overrideVersionCode = 5),
SingleLang("ManhuaZone", "https://manhuazone.org", "en", overrideVersionCode = 1),
@ -348,8 +349,8 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("Mantraz Scan", "https://mantrazscan.com", "es"),
SingleLang("ManWe", "https://manwe.pro", "tr", className = "EvaScans", overrideVersionCode = 1),
SingleLang("ManyComic", "https://manycomic.com", "en", isNsfw = true, overrideVersionCode = 1),
SingleLang("ManyToon", "https://manytoon.com", "en", isNsfw = true, overrideVersionCode = 5),
SingleLang("ManyToon.me", "https://manytoon.me", "en", isNsfw = true, className = "ManyToonMe", overrideVersionCode = 5),
SingleLang("ManyToon", "https://manytoon.com", "en", isNsfw = true, overrideVersionCode = 5),
SingleLang("ManyToonClub", "https://manytoon.club", "ko", isNsfw = true, overrideVersionCode = 2),
SingleLang("MG Komik", "https://mgkomik.id", "id", overrideVersionCode = 11),
SingleLang("Midnight Mess Scans", "https://midnightmess.org", "en", isNsfw = true, overrideVersionCode = 6),
@ -371,11 +372,9 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("NekoPost.co (unoriginal)", "https://www.nekopost.co", "th", isNsfw = false, className = "NekoPostCo"),
SingleLang("NekoScan", "https://nekoscan.com", "en", overrideVersionCode = 2),
SingleLang("NewManhua", "https://newmanhua.com", "en", isNsfw = true),
SingleLang("Nexo Scans", "https://nexoscans.com", "pt-BR", overrideVersionCode = 1),
SingleLang("Night Comic", "https://www.nightcomic.com", "en", overrideVersionCode = 1),
SingleLang("Niji Translations", "https://niji-translations.com", "ar", overrideVersionCode = 1),
SingleLang("Nitro Manga", "https://nitromanga.com", "en", className = "NitroScans", overrideVersionCode = 1),
SingleLang("Norte Rose Scan", "https://norterose.com.br", "pt-BR", isNsfw = true),
SingleLang("No Index Scan", "https://noindexscan.com", "pt-BR", isNsfw = true),
SingleLang("Noblesse Translations", "https://www.noblessev1.com", "es", overrideVersionCode = 2),
SingleLang("Nocturne Summer", "https://nocsummer.com.br", "pt-BR", isNsfw = true),
@ -454,7 +453,6 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("Tatakae Scan", "https://tatakaescan.com", "pt-BR", isNsfw = true, overrideVersionCode = 2),
SingleLang("Taurus Fansub", "https://taurusmanga.com", "es", overrideVersionCode = 1),
SingleLang("TeenManhua", "https://teenmanhua.com", "en", overrideVersionCode = 1),
SingleLang("TenkaiScan", "https://tenkaiscan.net", "es", isNsfw = true),
SingleLang("The Beginning After The End", "https://www.thebeginningaftertheend.fr", "fr", overrideVersionCode = 1),
SingleLang("The Blank Scanlation", "https://theblank.net", "en", className = "TheBlank", isNsfw = true),
SingleLang("The Guild", "https://theguildscans.com", "en"),
@ -504,19 +502,18 @@ class MadaraGenerator : ThemeSourceGenerator {
SingleLang("Yuri Verso", "https://yuri.live", "pt-BR", overrideVersionCode = 3),
SingleLang("Zandy no Fansub", "https://zandynofansub.aishiteru.org", "en"),
SingleLang("ZinChanManga", "https://zinchanmanga.com", "en", isNsfw = true),
SingleLang("Zinmanga", "https://zinmanga.com", "en", overrideVersionCode = 1),
SingleLang("ZinManga.top (unoriginal)", "https://zinmanga.top", "en", isNsfw = false, className = "ZinMangaTop"),
SingleLang("Zinmanga", "https://zinmanga.com", "en", overrideVersionCode = 1),
SingleLang("Zinmanhwa", "https://zinmanhwa.com", "en"),
SingleLang("ZuttoManga", "https://zuttomanga.com", "en", overrideVersionCode = 1),
SingleLang("Çizgi Roman Arşivi", "https://cizgiromanarsivi.com", "tr", className = "CizgiRomanArsivi"),
SingleLang("شبكة كونان العربية", "https://manga.detectiveconanar.com", "ar", className = "DetectiveConanAr", overrideVersionCode = 2),
SingleLang("عرب تونز", "https://arabtoons.net", "ar", isNsfw = true, className = "ArabToons"),
SingleLang("فالكون مانجا", "https://falconmanga.com", "ar", className = "FalconManga"),
SingleLang("كوميك العرب", "https://comicarab.com", "ar", isNsfw = true, className = "ComicArab"),
SingleLang("مانجا العاشق", "https://3asq.org", "ar", className = "Manga3asq", overrideVersionCode = 2),
SingleLang("مانجا ليك", "https://manga-lek.net", "ar", className = "Mangalek", overrideVersionCode = 4),
SingleLang("مانجا ليكس", "https://mangaleks.com", "ar", className = "MangaLeks"),
SingleLang("مانجا لينك", "https://mangalink.io", "ar", className = "MangaLinkio", overrideVersionCode = 3),
SingleLang("كوميك العرب", "https://comicarab.com", "ar", isNsfw = true, className = "ComicArab"),
SingleLang("فالكون مانجا", "https://falconmanga.com", "ar", className = "FalconManga"),
SingleLang("巴卡漫画", "https://bakamh.com", "zh", isNsfw = true, className = "Bakamh"),
)

View File

@ -277,7 +277,7 @@ abstract class MadTheme(
}
override fun imageUrlParse(document: Document): String =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used.")
// Date logic lifted from Madara
private fun parseChapterDate(date: String?): Long {

View File

@ -269,7 +269,7 @@ abstract class MangaBox(
return GET(page.imageUrl!!, headersBuilder().set("Referer", page.url).build())
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
// Based on change_alias JS function from Mangakakalot's website
@SuppressLint("DefaultLocale")

View File

@ -36,16 +36,16 @@ abstract class MangaCatalog(
title = name
url = sourceurl
}
override fun popularMangaRequest(page: Int): Request = throw UnsupportedOperationException()
override fun popularMangaNextPageSelector(): String? = throw UnsupportedOperationException()
override fun popularMangaSelector(): String = throw UnsupportedOperationException()
override fun popularMangaFromElement(element: Element) = throw UnsupportedOperationException()
override fun popularMangaRequest(page: Int): Request = throw Exception("Not used")
override fun popularMangaNextPageSelector(): String? = throw Exception("Not used")
override fun popularMangaSelector(): String = throw Exception("Not used")
override fun popularMangaFromElement(element: Element) = throw Exception("Not used")
// Latest
override fun latestUpdatesRequest(page: Int): Request = throw UnsupportedOperationException()
override fun latestUpdatesNextPageSelector(): String? = throw UnsupportedOperationException()
override fun latestUpdatesSelector(): String = throw UnsupportedOperationException()
override fun latestUpdatesFromElement(element: Element): SManga = throw UnsupportedOperationException()
override fun latestUpdatesRequest(page: Int): Request = throw Exception("Not used")
override fun latestUpdatesNextPageSelector(): String? = throw Exception("Not used")
override fun latestUpdatesSelector(): String = throw Exception("Not used")
override fun latestUpdatesFromElement(element: Element): SManga = throw Exception("Not used")
// Search
@ -59,10 +59,10 @@ abstract class MangaCatalog(
return Observable.just(MangasPage(mangas, false))
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = throw UnsupportedOperationException()
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException()
override fun searchMangaSelector() = throw UnsupportedOperationException()
override fun searchMangaFromElement(element: Element) = throw UnsupportedOperationException()
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = throw Exception("Not used")
override fun searchMangaNextPageSelector() = throw Exception("Not used")
override fun searchMangaSelector() = throw Exception("Not used")
override fun searchMangaFromElement(element: Element) = throw Exception("Not used")
// Get Override
@ -106,5 +106,5 @@ abstract class MangaCatalog(
Page(index, "", img.attr("src"))
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document): String = throw Exception("Not Used")
}

View File

@ -116,7 +116,7 @@ abstract class MangAdventure(
}
override fun imageUrlParse(response: Response) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun getMangaUrl(manga: SManga) = "$baseUrl/reader/${manga.url}"

View File

@ -279,7 +279,7 @@ abstract class MangaHub(
}
override fun chapterFromElement(element: Element): SChapter {
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not Used")
}
private fun parseChapterDate(date: String): Long {
@ -361,7 +361,7 @@ abstract class MangaHub(
.doOnError { refreshApiKey(chapter) }
.retry(1)
override fun pageListParse(document: Document): List<Page> = throw UnsupportedOperationException()
override fun pageListParse(document: Document): List<Page> = throw UnsupportedOperationException("Not used")
override fun pageListParse(response: Response): List<Page> {
val chapterObject = json.decodeFromString<ApiChapterPagesResponse>(response.body.string())
@ -393,7 +393,7 @@ abstract class MangaHub(
return GET(page.url, newHeaders)
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
// filters
private class Genre(title: String, val key: String) : Filter.TriState(title) {

View File

@ -78,5 +78,5 @@ abstract class MangaRawTheme(
}
}
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used.")
}

View File

@ -503,15 +503,15 @@ abstract class MangaThemesia(
protected open fun Elements.imgAttr(): String = this.first()!!.imgAttr()
// Unused
override fun popularMangaSelector(): String = throw UnsupportedOperationException()
override fun popularMangaFromElement(element: Element): SManga = throw UnsupportedOperationException()
override fun popularMangaNextPageSelector(): String? = throw UnsupportedOperationException()
override fun popularMangaSelector(): String = throw UnsupportedOperationException("Not used")
override fun popularMangaFromElement(element: Element): SManga = throw UnsupportedOperationException("Not used")
override fun popularMangaNextPageSelector(): String? = throw UnsupportedOperationException("Not used")
override fun latestUpdatesSelector(): String = throw UnsupportedOperationException()
override fun latestUpdatesFromElement(element: Element): SManga = throw UnsupportedOperationException()
override fun latestUpdatesNextPageSelector(): String? = throw UnsupportedOperationException()
override fun latestUpdatesSelector(): String = throw UnsupportedOperationException("Not used")
override fun latestUpdatesFromElement(element: Element): SManga = throw UnsupportedOperationException("Not used")
override fun latestUpdatesNextPageSelector(): String? = throw UnsupportedOperationException("Not used")
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not Used")
override fun setupPreferenceScreen(screen: PreferenceScreen) {
addRandomUAPreferenceToScreen(screen)

View File

@ -30,7 +30,7 @@ class MangaThemesiaGenerator : ThemeSourceGenerator {
SingleLang("Berserker Scan", "https://ragnascan.com", "es"),
SingleLang("BirdManga", "https://birdmanga.com", "en"),
SingleLang("Boosei", "https://boosei.net", "id", overrideVersionCode = 2),
SingleLang("Cartel de Manhwas", "https://carteldemanhwas.com", "es", overrideVersionCode = 6),
SingleLang("Cartel de Manhwas", "https://carteldemanhwas.com", "es", overrideVersionCode = 5),
SingleLang("Constellar Scans", "https://constellarcomic.com", "en", isNsfw = true, overrideVersionCode = 16),
SingleLang("Cosmic Scans", "https://cosmic-scans.com", "en", overrideVersionCode = 2),
SingleLang("CosmicScans.id", "https://cosmicscans.id", "id", overrideVersionCode = 3, className = "CosmicScansID"),
@ -68,8 +68,8 @@ class MangaThemesiaGenerator : ThemeSourceGenerator {
SingleLang("KomikIndo.co", "https://komikindo.co", "id", className = "KomikindoCo", overrideVersionCode = 3),
SingleLang("KomikMama", "https://komikmama.co", "id", overrideVersionCode = 1),
SingleLang("KomikManhwa", "https://komikmanhwa.me", "id", isNsfw = true),
SingleLang("Komiksan", "https://komiksan.link", "id", overrideVersionCode = 2),
SingleLang("Komiktap", "https://komiktap.me", "id", isNsfw = true),
SingleLang("Komiksan", "https://komiksan.link", "id", overrideVersionCode = 2),
SingleLang("Komiku.com", "https://komiku.com", "id", className = "KomikuCom"),
SingleLang("Kuma Scans (Kuma Translation)", "https://kumascans.com", "en", className = "KumaScans", overrideVersionCode = 1),
SingleLang("KumaPoi", "https://kumapoi.info", "id", isNsfw = true, overrideVersionCode = 3),
@ -86,6 +86,7 @@ class MangaThemesiaGenerator : ThemeSourceGenerator {
SingleLang("Mangacim", "https://www.mangacim.com", "tr", overrideVersionCode = 1),
SingleLang("MangaKita", "https://mangakita.id", "id", overrideVersionCode = 2),
SingleLang("Mangakyo", "https://mangakyo.org", "id", overrideVersionCode = 3),
SingleLang("Mangás Chan", "https://mangaschan.net", "pt-BR", className = "MangasChan", overrideVersionCode = 1),
SingleLang("MangaShiina", "https://mangashiina.com", "es"),
SingleLang("MangaShiro", "https://mangashiro.me", "id"),
SingleLang("Mangasusu", "https://mangasusuku.xyz", "id", isNsfw = true, overrideVersionCode = 3),
@ -93,7 +94,6 @@ class MangaThemesiaGenerator : ThemeSourceGenerator {
SingleLang("MangaTale", "https://mangatale.co", "id", overrideVersionCode = 1),
SingleLang("MangaWT", "https://mangawt.com", "tr", overrideVersionCode = 5),
SingleLang("Mangayaro", "https://www.mangayaro.id", "id", overrideVersionCode = 1),
SingleLang("Mangás Chan", "https://mangaschan.net", "pt-BR", className = "MangasChan", overrideVersionCode = 1),
SingleLang("Mangás Online", "https://mangasonline.cc", "pt-BR", className = "MangasOnline"),
SingleLang("Manhwa Freak", "https://manhwa-freak.com", "en", overrideVersionCode = 3),
SingleLang("Manhwa Lover", "https://manhwalover.com", "en", isNsfw = true, overrideVersionCode = 1),
@ -137,7 +137,6 @@ class MangaThemesiaGenerator : ThemeSourceGenerator {
SingleLang("Senpai Ediciones", "http://senpaiediciones.com", "es", overrideVersionCode = 1),
SingleLang("Shadow Mangas", "https://shadowmangas.com", "es", overrideVersionCode = 1),
SingleLang("Shea Manga", "https://sheakomik.com", "id", overrideVersionCode = 4),
SingleLang("Shirakami", "https://shirakami.xyz", "id"),
SingleLang("Silence Scan", "https://silencescan.com.br", "pt-BR", isNsfw = true, overrideVersionCode = 5),
SingleLang("Siren Komik", "https://sirenkomik.my.id", "id", className = "MangKomik", overrideVersionCode = 2),
SingleLang("SkyMangas", "https://skymangas.com", "es", overrideVersionCode = 1),
@ -153,6 +152,7 @@ class MangaThemesiaGenerator : ThemeSourceGenerator {
SingleLang("Sushiscan.fr", "https://anime-sama.me", "fr", className = "SushiScanFR", overrideVersionCode = 1),
SingleLang("Tarot Scans", "https://www.tarotscans.com", "tr"),
SingleLang("Tecno Scan", "https://tecnoscann.com", "es", isNsfw = true, overrideVersionCode = 6),
SingleLang("TenkaiScan", "https://tenkaiscan.net", "es", isNsfw = true),
SingleLang("Tenshi.id", "https://tenshi.id", "id", className = "TenshiId", pkgName = "masterkomik", overrideVersionCode = 4),
SingleLang("The Apollo Team", "https://theapollo.team", "en"),
SingleLang("Tres Daos Scan", "https://tresdaos.com", "es"),

View File

@ -201,7 +201,7 @@ abstract class MangaWorld(
}
}
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used.")
override fun imageRequest(page: Page): Request {
val imgHeader = Headers.Builder().apply {

View File

@ -96,7 +96,7 @@ open class MCCMS(
}
}
override fun mangaDetailsParse(response: Response): SManga = throw UnsupportedOperationException()
override fun mangaDetailsParse(response: Response): SManga = throw UnsupportedOperationException("Not used.")
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> = Observable.fromCallable {
val id = getMangaId(manga.url)
@ -112,7 +112,7 @@ open class MCCMS(
protected open fun getMangaId(url: String) = url.substringAfterLast('/')
override fun chapterListParse(response: Response): List<SChapter> = throw UnsupportedOperationException()
override fun chapterListParse(response: Response): List<SChapter> = throw UnsupportedOperationException("Not used.")
override fun pageListRequest(chapter: SChapter): Request =
GET(baseUrl + chapter.url, pcHeaders)
@ -126,7 +126,7 @@ open class MCCMS(
}
}
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Not used.")
override fun imageRequest(page: Page) = GET(page.imageUrl!!, pcHeaders)

View File

@ -420,7 +420,7 @@ abstract class MMRCMS(
Page(i, response.request.url.toString(), url)
}
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Unused method called!")
private fun getInitialFilterList() = listOf<Filter<*>>(
Filter.Header("NOTE: Ignored if using text search!"),

View File

@ -107,32 +107,32 @@ open class MonochromeCMS(
json.decodeFromString<T>(body.string())
override fun popularMangaRequest(page: Int) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun latestUpdatesRequest(page: Int) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun mangaDetailsRequest(manga: SManga) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun popularMangaParse(response: Response) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun latestUpdatesParse(response: Response) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun mangaDetailsParse(response: Response) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun chapterListParse(response: Response) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun pageListRequest(chapter: SChapter) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun pageListParse(response: Response) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun imageUrlParse(response: Response) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
}

View File

@ -262,7 +262,7 @@ abstract class MyMangaCMS(
override fun chapterListSelector(): String = "ul.list-chapters > a"
override fun chapterFromElement(element: Element): SChapter = throw UnsupportedOperationException()
override fun chapterFromElement(element: Element): SChapter = throw Exception("Not used")
private fun chapterFromElement(element: Element, scanlator: String?): SChapter =
SChapter.create().apply {
@ -307,7 +307,7 @@ abstract class MyMangaCMS(
.filterNot { it.attr("abs:data-src").isNullOrEmpty() }
.mapIndexed { index, elem -> Page(index, "", elem.attr("abs:data-src")) }
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document): String = throw Exception("Not used")
//endregion
//region Filters

View File

@ -227,7 +227,7 @@ abstract class NepNep(
return parseDirectory(1)
}
override fun searchMangaParse(response: Response): MangasPage = throw UnsupportedOperationException()
override fun searchMangaParse(response: Response): MangasPage = throw UnsupportedOperationException("Not used")
// Details
@ -357,7 +357,7 @@ abstract class NepNep(
}
}
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException()
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Not used")
// Filters

View File

@ -95,9 +95,9 @@ open class OtakuSanctuary(
return MangasPage(parseMangaCollection(collection), hasNextPage)
}
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException()
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException("Not used")
override fun latestUpdatesParse(response: Response) = throw UnsupportedOperationException()
override fun latestUpdatesParse(response: Response) = throw UnsupportedOperationException("Not used")
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request =
GET(
@ -176,7 +176,7 @@ open class OtakuSanctuary(
}
}
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Not used")
override fun pageListParse(response: Response): List<Page> {
val document = response.asJsoup()

View File

@ -130,7 +130,7 @@ abstract class Paprika(
// never called
override fun chapterFromElement(element: Element): SChapter {
throw UnsupportedOperationException()
throw Exception("unreachable code was reached!")
}
open fun chapterFromElement(element: Element, mangaTitle: String): SChapter {
@ -179,7 +179,7 @@ abstract class Paprika(
}
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
// Filters

View File

@ -174,15 +174,15 @@ abstract class ReadAllComics(
}
override fun imageUrlParse(document: Document) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not Implemented")
override fun latestUpdatesRequest(page: Int) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not Implemented")
override fun latestUpdatesFromElement(element: Element) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not Implemented")
override fun latestUpdatesSelector() =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not Implemented")
override fun latestUpdatesNextPageSelector() =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not Implemented")
override fun popularMangaFromElement(element: Element) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not Implemented")
}

View File

@ -165,11 +165,11 @@ abstract class ReaderFront(
private inline val JsonElement.content get() = jsonPrimitive.content
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun searchMangaParse(response: Response) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
override fun imageUrlParse(response: Response) =
throw UnsupportedOperationException()
throw UnsupportedOperationException("Not used!")
}

View File

@ -261,7 +261,7 @@ abstract class Senkuro(
chapterListParse(response, manga)
}
}
override fun chapterListParse(response: Response) = throw UnsupportedOperationException()
override fun chapterListParse(response: Response) = throw UnsupportedOperationException("chapterListParse(response: Response, manga: SManga)")
private fun chapterListParse(response: Response, manga: SManga): List<SChapter> {
val chaptersList = json.decodeFromString<PageWrapperDto<MangaTachiyomiChaptersDto>>(response.body.string())
val teamsList = chaptersList.data.mangaTachiyomiChapters.teams

View File

@ -215,7 +215,7 @@ abstract class SinMH(
emptyList() // []
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not Used.")
protected class UriPartFilter(displayName: String, values: Array<String>, private val uriParts: Array<String>) :
Filter.Select<String>(displayName, values) {

View File

@ -154,11 +154,11 @@ open class WebtoonsTranslate(
}
}
override fun chapterListSelector(): String = throw UnsupportedOperationException()
override fun chapterListSelector(): String = throw Exception("Not used")
override fun chapterFromElement(element: Element): SChapter = throw UnsupportedOperationException()
override fun chapterFromElement(element: Element): SChapter = throw Exception("Not used")
override fun pageListParse(document: Document): List<Page> = throw UnsupportedOperationException()
override fun pageListParse(document: Document): List<Page> = throw Exception("Not used")
override fun chapterListRequest(manga: SManga): Request {
val mangaUrl = manga.url.toHttpUrl()

View File

@ -220,7 +220,7 @@ abstract class WPComics(
.mapIndexed { i, image -> Page(i, "", image) }
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
// Filters

View File

@ -193,7 +193,7 @@ abstract class Zbulu(
}
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
// Filters

View File

@ -272,7 +272,7 @@ abstract class ZeistManga(
}
}
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Not used.")
protected open val mangaCategory: String = "Series"

View File

@ -174,7 +174,7 @@ abstract class ZManga(
}
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
open val hasProjectPage = false

View File

@ -69,6 +69,10 @@ interface ThemeSourceGenerator {
gradle.writeText(
"""
|// THIS FILE IS AUTO-GENERATED; DO NOT EDIT
|apply plugin: 'com.android.application'
|apply plugin: 'kotlin-android'
|apply plugin: 'kotlinx-serialization'
|
|ext {
| extName = '${source.name}'
| pkgNameSuffix = '${pkgNameSuffix(source, ".")}'
@ -77,11 +81,9 @@ interface ThemeSourceGenerator {
| extVersionCode = ${baseVersionCode + source.overrideVersionCode + multisrcLibraryVersion}
| ${if (source.isNsfw) "isNsfw = true\n" else ""}
|}
|
|apply from: "${'$'}rootDir/common.gradle"
|
|$defaultAdditionalGradleText
|$additionalGradleOverrideText
|apply from: "${'$'}rootDir/common.gradle"
|
|android {
| defaultConfig {
@ -90,7 +92,6 @@ interface ThemeSourceGenerator {
| ]
| }
|}
|
""".trimMargin(),
)
}
@ -108,7 +109,6 @@ interface ThemeSourceGenerator {
|<?xml version="1.0" encoding="utf-8"?>
|<!-- THIS FILE IS AUTO-GENERATED; DO NOT EDIT -->
|<manifest />
|
""".trimMargin(),
)
}

View File

@ -1,3 +1,6 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
ext {
extName = 'Akuma'
pkgNameSuffix = 'all.akuma'
@ -6,4 +9,4 @@ ext {
isNsfw = true
}
apply from: "$rootDir/common.gradle"
apply from: "$rootDir/common.gradle"

View File

@ -1,3 +1,7 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlinx-serialization'
ext {
extName = 'Bato.to'
pkgNameSuffix = 'all.batoto'

View File

@ -298,10 +298,10 @@ open class BatoTo(
add("prevPos", "null")
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = throw UnsupportedOperationException()
override fun searchMangaSelector() = throw UnsupportedOperationException()
override fun searchMangaFromElement(element: Element) = throw UnsupportedOperationException()
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException()
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = throw UnsupportedOperationException("Not used")
override fun searchMangaSelector() = throw UnsupportedOperationException("Not used")
override fun searchMangaFromElement(element: Element) = throw UnsupportedOperationException("Not used")
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException("Not used")
override fun mangaDetailsRequest(manga: SManga): Request {
if (manga.url.startsWith("http")) {
@ -456,7 +456,7 @@ open class BatoTo(
}
override fun pageListParse(document: Document): List<Page> {
val script = document.selectFirst("script:containsData(imgHttps):containsData(batoWord):containsData(batoPass)")?.html()
val script = document.selectFirst("script:containsData(imgHttpLis):containsData(batoWord):containsData(batoPass)")?.html()
?: throw RuntimeException("Couldn't find script with image data.")
val imgHttpsString = script.substringAfter("const imgHttps =").substringBefore(";").trim()
@ -473,7 +473,7 @@ open class BatoTo(
}
}
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
private fun String.removeEntities(): String = Parser.unescapeEntities(this, true)

View File

@ -1,3 +1,6 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
ext {
extName = 'Buon Dua'
pkgNameSuffix = 'all.buondua'

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