Compare commits
23 Commits
c353c9a780
...
d61cbfc0c1
Author | SHA1 | Date |
---|---|---|
Draff | d61cbfc0c1 | |
AwkwardPeak7 | c5f82e6aeb | |
stevenyomi | 4c8c21596b | |
stevenyomi | 3ceea4ab95 | |
Claudemirovsky | 35673b2199 | |
stevenyomi | 029932e3d8 | |
stevenyomi | 5023bde8ef | |
Claudemirovsky | fb2d7cfd23 | |
uy/sun | f8e98da8a6 | |
stevenyomi | 3e22055a7a | |
Claudemirovsky | d3da494cba | |
beerpsi | 172d11d9ea | |
AwkwardPeak7 | 205e138dd2 | |
Ruliam dos Santos de Oliveira | 4b155000b4 | |
uy/sun | f5f90f7a0e | |
Vetle Ledaal | 4feb5e77a5 | |
Claudemirovsky | ef9312261e | |
beerpsi | 04ca6e2fb7 | |
rtlow | 3045c7be96 | |
bapeey | e6dba52ab9 | |
bapeey | c8df4afffd | |
Draff | c82ebd9e0f | |
bapeey | 6f0d4d21b8 |
|
@ -7,3 +7,4 @@ Checklist:
|
||||||
- [ ] Have not changed source names
|
- [ ] Have not changed source names
|
||||||
- [ ] Have explicitly kept the `id` if a source's name or language were changed
|
- [ ] 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 tested the modifications by compiling and running the extension through Android Studio
|
||||||
|
- [ ] Have removed `web_hi_res_512.png` when adding a new extension
|
||||||
|
|
|
@ -37,8 +37,8 @@ jobs:
|
||||||
- name: Set up JDK
|
- name: Set up JDK
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 17
|
||||||
distribution: adopt
|
distribution: temurin
|
||||||
|
|
||||||
- name: Prepare signing key
|
- name: Prepare signing key
|
||||||
run: |
|
run: |
|
||||||
|
@ -82,8 +82,8 @@ jobs:
|
||||||
- name: Set up JDK
|
- name: Set up JDK
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
java-version: 17
|
||||||
distribution: adopt
|
distribution: temurin
|
||||||
|
|
||||||
- name: Prepare signing key
|
- name: Prepare signing key
|
||||||
run: |
|
run: |
|
||||||
|
@ -125,7 +125,7 @@ jobs:
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
java-version: 17
|
java-version: 17
|
||||||
distribution: adopt
|
distribution: temurin
|
||||||
|
|
||||||
- name: Checkout master branch
|
- name: Checkout master branch
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
108
CONTRIBUTING.md
|
@ -6,31 +6,54 @@ This guide is not definitive and it's being updated over time. If you find any i
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
1. [Prerequisites](#prerequisites)
|
- [Contributing](#contributing)
|
||||||
1. [Tools](#tools)
|
- [Table of Contents](#table-of-contents)
|
||||||
2. [Cloning the repository](#cloning-the-repository)
|
- [Prerequisites](#prerequisites)
|
||||||
2. [Getting help](#getting-help)
|
- [Tools](#tools)
|
||||||
3. [Writing an extension](#writing-an-extension)
|
- [Cloning the repository](#cloning-the-repository)
|
||||||
1. [Setting up a new Gradle module](#setting-up-a-new-gradle-module)
|
- [Getting help](#getting-help)
|
||||||
2. [Core dependencies](#core-dependencies)
|
- [Writing an extension](#writing-an-extension)
|
||||||
3. [Extension main class](#extension-main-class)
|
- [Setting up a new Gradle module](#setting-up-a-new-gradle-module)
|
||||||
4. [Extension call flow](#extension-call-flow)
|
- [Loading a subset of Gradle modules](#loading-a-subset-of-gradle-modules)
|
||||||
5. [Misc notes](#misc-notes)
|
- [Extension file structure](#extension-file-structure)
|
||||||
6. [Advanced extension features](#advanced-extension-features)
|
- [AndroidManifest.xml](#androidmanifestxml)
|
||||||
4. [Multi-source themes](#multi-source-themes)
|
- [build.gradle](#buildgradle)
|
||||||
1. [The directory structure](#the-directory-structure)
|
- [Core dependencies](#core-dependencies)
|
||||||
2. [Development workflow](#development-workflow)
|
- [Extension API](#extension-api)
|
||||||
3. [Scaffolding overrides](#scaffolding-overrides)
|
- [DataImage library](#dataimage-library)
|
||||||
4. [Additional Notes](#additional-notes)
|
- [i18n library](#i18n-library)
|
||||||
5. [Running](#running)
|
- [Additional dependencies](#additional-dependencies)
|
||||||
6. [Debugging](#debugging)
|
- [Extension main class](#extension-main-class)
|
||||||
1. [Android Debugger](#android-debugger)
|
- [Main class key variables](#main-class-key-variables)
|
||||||
2. [Logs](#logs)
|
- [Extension call flow](#extension-call-flow)
|
||||||
3. [Inspecting network calls](#inspecting-network-calls)
|
- [Popular Manga](#popular-manga)
|
||||||
4. [Using external network inspecting tools](#using-external-network-inspecting-tools)
|
- [Latest Manga](#latest-manga)
|
||||||
7. [Building](#building)
|
- [Manga Search](#manga-search)
|
||||||
8. [Submitting the changes](#submitting-the-changes)
|
- [Filters](#filters)
|
||||||
1. [Pull Request checklist](#pull-request-checklist)
|
- [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)
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
|
@ -201,9 +224,8 @@ src/<lang>/<mysourcename>/
|
||||||
│ │ └── ic_launcher.png
|
│ │ └── ic_launcher.png
|
||||||
│ ├── mipmap-xxhdpi
|
│ ├── mipmap-xxhdpi
|
||||||
│ │ └── ic_launcher.png
|
│ │ └── ic_launcher.png
|
||||||
│ ├── mipmap-xxxhdpi
|
│ └── mipmap-xxxhdpi
|
||||||
│ │ └── ic_launcher.png
|
│ └── ic_launcher.png
|
||||||
│ └── web_hi_res_512.png
|
|
||||||
└── src
|
└── src
|
||||||
└── eu
|
└── eu
|
||||||
└── kanade
|
└── kanade
|
||||||
|
@ -223,9 +245,6 @@ 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:
|
Make sure that your new extension's `build.gradle` file follows the following structure:
|
||||||
|
|
||||||
```gradle
|
```gradle
|
||||||
apply plugin: 'com.android.application'
|
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
extName = '<My source name>'
|
extName = '<My source name>'
|
||||||
pkgNameSuffix = '<lang>.<mysourcename>'
|
pkgNameSuffix = '<lang>.<mysourcename>'
|
||||||
|
@ -415,10 +434,15 @@ open class UriPartFilter(displayName: String, private val vals: Array<Pair<Strin
|
||||||
|
|
||||||
### Misc notes
|
### Misc notes
|
||||||
|
|
||||||
- Sometimes you may find no use for some inherited methods. If so just override them and throw exceptions: `throw UnsupportedOperationException("Not used.")`
|
- Sometimes you may find no use for some inherited methods. If so just override them and throw
|
||||||
- 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`).
|
exceptions: `throw UnsupportedOperationException()`
|
||||||
- If possible try to stick to the general workflow from `HttpSource`/`ParsedHttpSource`; breaking them may cause you more headache than necessary.
|
- You probably will find `getUrlWithoutDomain` useful when parsing the target source URLs. Keep in
|
||||||
- By implementing `ConfigurableSource` you can add settings to your source, which is backed by [`SharedPreferences`](https://developer.android.com/reference/android/content/SharedPreferences).
|
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
|
### Advanced Extension features
|
||||||
|
|
||||||
|
@ -495,9 +519,8 @@ multisrc
|
||||||
│ │ │ └── ic_launcher.png
|
│ │ │ └── ic_launcher.png
|
||||||
│ │ ├── mipmap-xxhdpi
|
│ │ ├── mipmap-xxhdpi
|
||||||
│ │ │ └── ic_launcher.png
|
│ │ │ └── ic_launcher.png
|
||||||
│ │ ├── mipmap-xxxhdpi
|
│ │ └── mipmap-xxxhdpi
|
||||||
│ │ │ └── ic_launcher.png
|
│ │ └── ic_launcher.png
|
||||||
│ │ └── web_hi_res_512.png
|
|
||||||
│ └── <sourcepkg>
|
│ └── <sourcepkg>
|
||||||
│ ├── additional.gradle
|
│ ├── additional.gradle
|
||||||
│ ├── AndroidManifest.xml
|
│ ├── AndroidManifest.xml
|
||||||
|
@ -510,9 +533,8 @@ multisrc
|
||||||
│ │ │ └── ic_launcher.png
|
│ │ │ └── ic_launcher.png
|
||||||
│ │ ├── mipmap-xxhdpi
|
│ │ ├── mipmap-xxhdpi
|
||||||
│ │ │ └── ic_launcher.png
|
│ │ │ └── ic_launcher.png
|
||||||
│ │ ├── mipmap-xxxhdpi
|
│ │ └── mipmap-xxxhdpi
|
||||||
│ │ │ └── ic_launcher.png
|
│ │ └── ic_launcher.png
|
||||||
│ │ └── web_hi_res_512.png
|
|
||||||
│ └── src
|
│ └── src
|
||||||
│ └── <SourceName>.kt
|
│ └── <SourceName>.kt
|
||||||
└── src
|
└── src
|
||||||
|
@ -739,7 +761,9 @@ 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.
|
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]
|
> [!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 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`.
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlinx-serialization'
|
||||||
apply plugin: 'org.jmailen.kotlinter'
|
apply plugin: 'org.jmailen.kotlinter'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
@ -25,7 +28,9 @@ android {
|
||||||
applicationIdSuffix pkgNameSuffix
|
applicationIdSuffix pkgNameSuffix
|
||||||
versionCode extVersionCode
|
versionCode extVersionCode
|
||||||
versionName project.ext.properties.getOrDefault("libVersion", "1.4") + ".$extVersionCode"
|
versionName project.ext.properties.getOrDefault("libVersion", "1.4") + ".$extVersionCode"
|
||||||
setProperty("archivesBaseName", "tachiyomi-$pkgNameSuffix-v$versionName")
|
base {
|
||||||
|
archivesName = "tachiyomi-$pkgNameSuffix-v$versionName"
|
||||||
|
}
|
||||||
def readmes = project.projectDir.listFiles({ File file ->
|
def readmes = project.projectDir.listFiles({ File file ->
|
||||||
file.name == "README.md" || file.name == "CHANGELOG.md"
|
file.name == "README.md" || file.name == "CHANGELOG.md"
|
||||||
} as FileFilter)
|
} as FileFilter)
|
||||||
|
@ -71,6 +76,7 @@ android {
|
||||||
renderScript false
|
renderScript false
|
||||||
resValues false
|
resValues false
|
||||||
shaders false
|
shaders false
|
||||||
|
buildConfig true
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
|
|
@ -9,7 +9,7 @@ android {
|
||||||
minSdk = AndroidConfig.minSdk
|
minSdk = AndroidConfig.minSdk
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace = "eu.kanade.tachiyomi.extension"
|
namespace = "eu.kanade.tachiyomi.extension.core"
|
||||||
|
|
||||||
@Suppress("UnstableApiUsage")
|
@Suppress("UnstableApiUsage")
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
|
|
@ -21,3 +21,5 @@ org.gradle.caching=true
|
||||||
|
|
||||||
# Enable AndroidX dependencies
|
# Enable AndroidX dependencies
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
|
android.nonTransitiveRClass=false
|
||||||
|
android.nonFinalResIds=false
|
||||||
|
|
|
@ -4,7 +4,7 @@ coroutines_version = "1.6.4"
|
||||||
serialization_version = "1.4.0"
|
serialization_version = "1.4.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
gradle-agp = { module = "com.android.tools.build:gradle", version = "7.4.2" }
|
gradle-agp = { module = "com.android.tools.build:gradle", version = "8.2.1" }
|
||||||
gradle-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin_version" }
|
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-serialization = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlin_version" }
|
||||||
gradle-kotlinter = { module = "org.jmailen.gradle:kotlinter-gradle", version = "3.13.0" }
|
gradle-kotlinter = { module = "org.jmailen.gradle:kotlinter-gradle", version = "3.13.0" }
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,15 @@ class MangaTR : FMReader("Manga-TR", "https://manga-tr.com", "tr") {
|
||||||
override fun headersBuilder() = super.headersBuilder()
|
override fun headersBuilder() = super.headersBuilder()
|
||||||
.add("Accept-Language", "en-US,en;q=0.5")
|
.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"
|
override fun popularMangaNextPageSelector() = "div.btn-group:not(div.btn-block) button.btn-info"
|
||||||
|
|
||||||
// =============================== Search ===============================
|
// =============================== Search ===============================
|
||||||
|
|
0
multisrc/overrides/guya/magicaltranslators/res/mipmap-hdpi/ic_launcher.png
Executable file → Normal file
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
0
multisrc/overrides/guya/magicaltranslators/res/mipmap-mdpi/ic_launcher.png
Executable file → Normal file
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
0
multisrc/overrides/guya/magicaltranslators/res/mipmap-xhdpi/ic_launcher.png
Executable file → Normal file
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
0
multisrc/overrides/guya/magicaltranslators/res/mipmap-xxhdpi/ic_launcher.png
Executable file → Normal file
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
0
multisrc/overrides/guya/magicaltranslators/res/mipmap-xxxhdpi/ic_launcher.png
Executable file → Normal file
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
@ -0,0 +1,9 @@
|
||||||
|
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/"
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import eu.kanade.tachiyomi.multisrc.madara.Madara
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
|
import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import okhttp3.CacheControl
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
|
@ -23,17 +24,47 @@ class MangasNoSekai : Madara(
|
||||||
|
|
||||||
override val useNewChapterEndpoint = true
|
override val useNewChapterEndpoint = true
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/${searchPage(page)}?s=&post_type=wp-manga&m_orderby=views", headers)
|
override val mangaSubString = "manganews"
|
||||||
|
|
||||||
override fun popularMangaSelector() = searchMangaSelector()
|
override fun popularMangaRequest(page: Int): Request {
|
||||||
|
return GET(
|
||||||
|
url = "$baseUrl/$mangaSubString/${searchPage(page)}?m_orderby=views",
|
||||||
|
headers = headers,
|
||||||
|
cache = CacheControl.FORCE_NETWORK,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun popularMangaFromElement(element: Element) = searchMangaFromElement(element)
|
override fun popularMangaSelector() = "div.page-listing-item > div.row > div"
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/${searchPage(page)}?s=&post_type=wp-manga&m_orderby=latest", headers)
|
override val popularMangaUrlSelector = "a[href]"
|
||||||
|
|
||||||
override fun latestUpdatesSelector() = searchMangaSelector()
|
override fun popularMangaFromElement(element: Element): SManga {
|
||||||
|
val manga = SManga.create()
|
||||||
|
|
||||||
override fun latestUpdatesFromElement(element: Element) = searchMangaFromElement(element)
|
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 searchPage(page: Int): String {
|
override fun searchPage(page: Int): String {
|
||||||
return if (page > 1) "page/$page/" else ""
|
return if (page > 1) "page/$page/" else ""
|
||||||
|
@ -112,4 +143,14 @@ class MangasNoSekai : Madara(
|
||||||
|
|
||||||
return manga
|
return manga
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val orderByFilterOptionsValues: Array<String> = arrayOf(
|
||||||
|
"",
|
||||||
|
"latest2",
|
||||||
|
"alphabet",
|
||||||
|
"rating",
|
||||||
|
"trending",
|
||||||
|
"views2",
|
||||||
|
"new-manga",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 22 KiB |
|
@ -0,0 +1,24 @@
|
||||||
|
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)"
|
||||||
|
}
|
After Width: | Height: | Size: 8.0 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 39 KiB |
|
@ -0,0 +1,3 @@
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":lib-synchrony"))
|
||||||
|
}
|
|
@ -1,11 +1,28 @@
|
||||||
package eu.kanade.tachiyomi.extension.id.shinigami
|
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.multisrc.madara.Madara
|
||||||
import eu.kanade.tachiyomi.network.interceptor.rateLimit
|
import eu.kanade.tachiyomi.network.GET
|
||||||
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.decodeFromString
|
||||||
import okhttp3.Headers
|
import okhttp3.Headers
|
||||||
|
import okhttp3.Interceptor
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Response
|
||||||
|
import org.jsoup.nodes.Document
|
||||||
import org.jsoup.nodes.Element
|
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
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class Shinigami : Madara("Shinigami", "https://shinigamitoon.com", "id") {
|
class Shinigami : Madara("Shinigami", "https://shinigamitoon.com", "id") {
|
||||||
|
@ -16,15 +33,91 @@ class Shinigami : Madara("Shinigami", "https://shinigamitoon.com", "id") {
|
||||||
|
|
||||||
override fun searchPage(page: Int): String = if (page == 1) "" else "page/$page/"
|
override fun searchPage(page: Int): String = if (page == 1) "" else "page/$page/"
|
||||||
|
|
||||||
override val client: OkHttpClient = super.client.newBuilder()
|
private val preferences: SharedPreferences by lazy {
|
||||||
.rateLimit(4, 1, TimeUnit.SECONDS)
|
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()
|
.build()
|
||||||
|
|
||||||
override fun headersBuilder(): Headers.Builder = super.headersBuilder()
|
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)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
override fun headersBuilder(): Headers.Builder {
|
||||||
|
val builder = super.headersBuilder()
|
||||||
.add("Sec-Fetch-Dest", "document")
|
.add("Sec-Fetch-Dest", "document")
|
||||||
.add("Sec-Fetch-Mode", "navigate")
|
.add("Sec-Fetch-Mode", "navigate")
|
||||||
.add("Sec-Fetch-Site", "same-origin")
|
.add("Sec-Fetch-Site", "same-origin")
|
||||||
.add("Upgrade-Insecure-Requests", "1")
|
.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 val mangaSubString = "semua-series"
|
override val mangaSubString = "semua-series"
|
||||||
|
|
||||||
|
@ -43,4 +136,76 @@ class Shinigami : Madara("Shinigami", "https://shinigamitoon.com", "id") {
|
||||||
|
|
||||||
setUrlWithoutDomain(fixedUrl)
|
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""") }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
@ -0,0 +1,15 @@
|
||||||
|
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"
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package eu.kanade.tachiyomi.extension.es.carteldemanhwas
|
package eu.kanade.tachiyomi.extension.es.carteldemanhwas
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
|
import eu.kanade.tachiyomi.multisrc.mangathemesia.MangaThemesia
|
||||||
|
import org.jsoup.nodes.Element
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
|
@ -14,6 +15,13 @@ class CarteldeManhwas : MangaThemesia(
|
||||||
override val hasProjectPage = true
|
override val hasProjectPage = true
|
||||||
override val projectPageString = "/proyectos"
|
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)), " +
|
override fun searchMangaSelector() = ".utao .uta .imgu:not(:has(span.novelabel)), " +
|
||||||
".listupd .bs .bsx:not(:has(span.novelabel)), " +
|
".listupd .bs .bsx:not(:has(span.novelabel)), " +
|
||||||
".listo .bs .bsx:not(:has(span.novelabel))"
|
".listo .bs .bsx:not(:has(span.novelabel))"
|
||||||
|
|
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 7.7 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 23 KiB |
|
@ -0,0 +1,12 @@
|
||||||
|
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")),
|
||||||
|
)
|
Before Width: | Height: | Size: 60 KiB |
|
@ -1,12 +0,0 @@
|
||||||
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")),
|
|
||||||
)
|
|
|
@ -56,13 +56,13 @@ open class A3Manga(
|
||||||
|
|
||||||
override fun popularMangaNextPageSelector() = "li.next:not(.disabled)"
|
override fun popularMangaNextPageSelector() = "li.next:not(.disabled)"
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException("Not used")
|
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun latestUpdatesSelector() = throw UnsupportedOperationException("Not used")
|
override fun latestUpdatesSelector() = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException("Not used")
|
override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException("Not used")
|
override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
||||||
return when {
|
return when {
|
||||||
|
@ -92,11 +92,11 @@ open class A3Manga(
|
||||||
.build(),
|
.build(),
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun searchMangaSelector(): String = throw UnsupportedOperationException("Not used")
|
override fun searchMangaSelector(): String = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun searchMangaFromElement(element: Element): SManga = throw UnsupportedOperationException("Not used")
|
override fun searchMangaFromElement(element: Element): SManga = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException("Not used")
|
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun searchMangaParse(response: Response): MangasPage {
|
override fun searchMangaParse(response: Response): MangasPage {
|
||||||
val dto = response.parseAs<SearchResponseDto>()
|
val dto = response.parseAs<SearchResponseDto>()
|
||||||
|
@ -213,7 +213,7 @@ open class A3Manga(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
private inline fun <reified T> Response.parseAs(): T {
|
private inline fun <reified T> Response.parseAs(): T {
|
||||||
return json.decodeFromString(body.string())
|
return json.decodeFromString(body.string())
|
||||||
|
|
|
@ -134,35 +134,35 @@ abstract class BakkinReaderX(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int) =
|
override fun popularMangaRequest(page: Int) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int) =
|
override fun latestUpdatesRequest(page: Int) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun mangaDetailsRequest(manga: SManga) =
|
override fun mangaDetailsRequest(manga: SManga) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun searchMangaParse(response: Response) =
|
override fun searchMangaParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun popularMangaParse(response: Response) =
|
override fun popularMangaParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun latestUpdatesParse(response: Response) =
|
override fun latestUpdatesParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun mangaDetailsParse(response: Response) =
|
override fun mangaDetailsParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun chapterListParse(response: Response) =
|
override fun chapterListParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun pageListParse(response: Response) =
|
override fun pageListParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response) =
|
override fun imageUrlParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,19 +40,19 @@ open class ComicGamma(
|
||||||
thumbnail_url = element.selectFirst(Evaluator.Tag("img"))!!.absUrl("src")
|
thumbnail_url = element.selectFirst(Evaluator.Tag("img"))!!.absUrl("src")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException("Not used.")
|
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException()
|
||||||
override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException("Not used.")
|
override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException()
|
||||||
override fun latestUpdatesSelector() = throw UnsupportedOperationException("Not used.")
|
override fun latestUpdatesSelector() = throw UnsupportedOperationException()
|
||||||
override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException("Not used.")
|
override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> =
|
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> =
|
||||||
fetchPopularManga(page).map { p -> MangasPage(p.mangas.filter { it.title.contains(query) }, false) }
|
fetchPopularManga(page).map { p -> MangasPage(p.mangas.filter { it.title.contains(query) }, false) }
|
||||||
|
|
||||||
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException("Not used.")
|
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException()
|
||||||
override fun searchMangaSelector() = throw UnsupportedOperationException("Not used.")
|
override fun searchMangaSelector() = throw UnsupportedOperationException()
|
||||||
override fun searchMangaFromElement(element: Element) = throw UnsupportedOperationException("Not used.")
|
override fun searchMangaFromElement(element: Element) = throw UnsupportedOperationException()
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
|
||||||
throw UnsupportedOperationException("Not used.")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun pageListParse(document: Document) =
|
override fun pageListParse(document: Document) =
|
||||||
document.select("#content > div[data-ptimg]").mapIndexed { i, e ->
|
document.select("#content > div[data-ptimg]").mapIndexed { i, e ->
|
||||||
|
@ -91,7 +91,7 @@ open class ComicGamma(
|
||||||
override fun pageListRequest(chapter: SChapter) =
|
override fun pageListRequest(chapter: SChapter) =
|
||||||
GET(baseUrl + chapter.url.toNewChapterUrl(), headers)
|
GET(baseUrl + chapter.url.toNewChapterUrl(), headers)
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used.")
|
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
internal fun SimpleDateFormat.parseJST(date: String) = parse(date)?.apply {
|
internal fun SimpleDateFormat.parseJST(date: String) = parse(date)?.apply {
|
||||||
|
|
|
@ -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 fetchPopularManga(page: Int): Observable<MangasPage> = fetchManga("$baseUrl/comics/album/Various-Authors", page, "")
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int): Request = throw UnsupportedOperationException("Not used")
|
override fun popularMangaRequest(page: Int): Request = throw UnsupportedOperationException()
|
||||||
override fun popularMangaParse(response: Response): MangasPage = throw UnsupportedOperationException("Not used")
|
override fun popularMangaParse(response: Response): MangasPage = throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Latest
|
// Latest
|
||||||
|
|
||||||
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> = fetchManga("$baseUrl/comics/album/Various-Authors?sort=date", page, "date")
|
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("Not used")
|
override fun latestUpdatesRequest(page: Int): Request = throw UnsupportedOperationException()
|
||||||
override fun latestUpdatesParse(response: Response): MangasPage = throw UnsupportedOperationException("Not used")
|
override fun latestUpdatesParse(response: Response): MangasPage = throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Search
|
// Search
|
||||||
|
|
||||||
|
@ -228,8 +228,8 @@ open class EroMuse(override val name: String, override val baseUrl: String) : Ht
|
||||||
.map { response -> parseManga(response.asJsoup()) }
|
.map { response -> parseManga(response.asJsoup()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = throw UnsupportedOperationException("Not used")
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = throw UnsupportedOperationException()
|
||||||
override fun searchMangaParse(response: Response): MangasPage = throw UnsupportedOperationException("Not used")
|
override fun searchMangaParse(response: Response): MangasPage = throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Details
|
// Details
|
||||||
|
|
||||||
|
@ -332,7 +332,7 @@ open class EroMuse(override val name: String, override val baseUrl: String) : Ht
|
||||||
return parsePages(response.asJsoup())
|
return parsePages(response.asJsoup())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Filters
|
// Filters
|
||||||
|
|
||||||
|
|
|
@ -190,7 +190,7 @@ abstract class FansubsCat(
|
||||||
override fun pageListParse(response: Response): List<Page> = parsePageListFromJson(response)
|
override fun pageListParse(response: Response): List<Page> = parsePageListFromJson(response)
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response): String =
|
override fun imageUrlParse(response: Response): String =
|
||||||
throw UnsupportedOperationException("Not used")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Filter
|
// Filter
|
||||||
override fun getFilterList() = FilterList(
|
override fun getFilterList() = FilterList(
|
||||||
|
|
|
@ -263,7 +263,7 @@ abstract class FlixScans(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Not Used")
|
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
protected inline fun <reified T> Response.parseAs(): T =
|
protected inline fun <reified T> Response.parseAs(): T =
|
||||||
use { body.string() }.let(json::decodeFromString)
|
use { body.string() }.let(json::decodeFromString)
|
||||||
|
|
|
@ -333,7 +333,7 @@ abstract class FMReader(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
|
||||||
|
|
||||||
private class TextField(name: String, val key: String) : Filter.Text(name)
|
private class TextField(name: String, val key: String) : Filter.Text(name)
|
||||||
private class Status : Filter.Select<String>("Status", arrayOf("Any", "Completed", "Ongoing"))
|
private class Status : Filter.Select<String>("Status", arrayOf("Any", "Completed", "Ongoing"))
|
||||||
|
|
|
@ -14,7 +14,7 @@ class FMReaderGenerator : ThemeSourceGenerator {
|
||||||
override val sources = listOf(
|
override val sources = listOf(
|
||||||
SingleLang("Epik Manga", "https://www.epikmanga.com", "tr"),
|
SingleLang("Epik Manga", "https://www.epikmanga.com", "tr"),
|
||||||
SingleLang("KissLove", "https://klz9.com", "ja", isNsfw = true, overrideVersionCode = 4),
|
SingleLang("KissLove", "https://klz9.com", "ja", isNsfw = true, overrideVersionCode = 4),
|
||||||
SingleLang("Manga-TR", "https://manga-tr.com", "tr", className = "MangaTR", overrideVersionCode = 2),
|
SingleLang("Manga-TR", "https://manga-tr.com", "tr", className = "MangaTR", overrideVersionCode = 3),
|
||||||
SingleLang("ManhuaRock", "https://manhuarock.net", "vi", overrideVersionCode = 1),
|
SingleLang("ManhuaRock", "https://manhuarock.net", "vi", overrideVersionCode = 1),
|
||||||
SingleLang("Say Truyen", "https://saytruyenvip.com", "vi", overrideVersionCode = 3),
|
SingleLang("Say Truyen", "https://saytruyenvip.com", "vi", overrideVersionCode = 3),
|
||||||
SingleLang("WeLoveManga", "https://weloma.art", "ja", pkgName = "rawlh", isNsfw = true, overrideVersionCode = 5),
|
SingleLang("WeLoveManga", "https://weloma.art", "ja", pkgName = "rawlh", isNsfw = true, overrideVersionCode = 5),
|
||||||
|
|
|
@ -271,7 +271,7 @@ abstract class FoolSlide(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
protected val preferences by lazy {
|
protected val preferences by lazy {
|
||||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)!!
|
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)!!
|
||||||
|
|
|
@ -255,7 +255,7 @@ abstract class GroupLe(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chapterFromElement(element: Element): SChapter {
|
override fun chapterFromElement(element: Element): SChapter {
|
||||||
throw Exception("Not used")
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun prepareNewChapter(chapter: SChapter, manga: SManga) {
|
override fun prepareNewChapter(chapter: SChapter, manga: SManga) {
|
||||||
|
@ -288,6 +288,11 @@ abstract class GroupLe(
|
||||||
|
|
||||||
var readerMark = "rm_h.readerDoInit(["
|
var readerMark = "rm_h.readerDoInit(["
|
||||||
|
|
||||||
|
// allhentai necessary
|
||||||
|
if (!html.contains(readerMark)) {
|
||||||
|
readerMark = "rm_h.readerInit( 0,["
|
||||||
|
}
|
||||||
|
|
||||||
if (!html.contains(readerMark)) {
|
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)) {
|
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")
|
throw Exception("Для просмотра контента необходима авторизация через WebView\uD83C\uDF0E")
|
||||||
|
|
|
@ -9,7 +9,7 @@ class GroupLeGenerator : ThemeSourceGenerator {
|
||||||
|
|
||||||
override val themeClass = "GroupLe"
|
override val themeClass = "GroupLe"
|
||||||
|
|
||||||
override val baseVersionCode = 21
|
override val baseVersionCode = 22
|
||||||
|
|
||||||
override val sources = listOf(
|
override val sources = listOf(
|
||||||
SingleLang("ReadManga", "https://readmanga.live", "ru", overrideVersionCode = 46),
|
SingleLang("ReadManga", "https://readmanga.live", "ru", overrideVersionCode = 46),
|
||||||
|
|
|
@ -455,7 +455,7 @@ abstract class Guya(
|
||||||
// ----------------- Things we aren't supporting -----------------
|
// ----------------- Things we aren't supporting -----------------
|
||||||
|
|
||||||
override fun mangaDetailsParse(response: Response): SManga {
|
override fun mangaDetailsParse(response: Response): SManga {
|
||||||
throw UnsupportedOperationException("Unused")
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
|
@ -467,11 +467,11 @@ abstract class Guya(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun searchMangaParse(response: Response): MangasPage {
|
override fun searchMangaParse(response: Response): MangasPage {
|
||||||
throw UnsupportedOperationException("Unused.")
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response): String {
|
override fun imageUrlParse(response: Response): String {
|
||||||
throw UnsupportedOperationException("Unused.")
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -274,7 +274,7 @@ abstract class HentaiHand(
|
||||||
Page(index, "", imgUrl)
|
Page(index, "", imgUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Authorization
|
// Authorization
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ abstract class LibGroup(
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
// Latest
|
// Latest
|
||||||
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException("Not used") // popularMangaRequest()
|
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException() // popularMangaRequest()
|
||||||
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> {
|
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> {
|
||||||
if (csrfToken.isEmpty()) {
|
if (csrfToken.isEmpty()) {
|
||||||
return client.newCall(popularMangaRequest(page))
|
return client.newCall(popularMangaRequest(page))
|
||||||
|
|
|
@ -285,7 +285,7 @@ abstract class Madara(
|
||||||
else -> arrayOf("Completed", "Ongoing", "Canceled", "On Hold")
|
else -> arrayOf("Completed", "Ongoing", "Canceled", "On Hold")
|
||||||
}
|
}
|
||||||
|
|
||||||
protected val statusFilterOptionsValues: Array<String> = arrayOf(
|
protected open val statusFilterOptionsValues: Array<String> = arrayOf(
|
||||||
"end",
|
"end",
|
||||||
"on-going",
|
"on-going",
|
||||||
"canceled",
|
"canceled",
|
||||||
|
@ -318,7 +318,7 @@ abstract class Madara(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected val orderByFilterOptionsValues: Array<String> = arrayOf(
|
protected open val orderByFilterOptionsValues: Array<String> = arrayOf(
|
||||||
"",
|
"",
|
||||||
"latest",
|
"latest",
|
||||||
"alphabet",
|
"alphabet",
|
||||||
|
|
|
@ -65,7 +65,6 @@ class MadaraGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("Cat300", "https://cat300.com", "th", isNsfw = true, className = "Cat300", overrideVersionCode = 1),
|
SingleLang("Cat300", "https://cat300.com", "th", isNsfw = true, className = "Cat300", overrideVersionCode = 1),
|
||||||
SingleLang("CatOnHeadTranslations", "https://catonhead.com", "en", overrideVersionCode = 2),
|
SingleLang("CatOnHeadTranslations", "https://catonhead.com", "en", overrideVersionCode = 2),
|
||||||
SingleLang("Cerise Scan", "https://cerisescan.com", "pt-BR", pkgName = "cerisescans", isNsfw = true, overrideVersionCode = 7),
|
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("Clover Manga", "https://clover-manga.com", "tr", overrideVersionCode = 2),
|
||||||
SingleLang("Coco Rip", "https://cocorip.net", "es"),
|
SingleLang("Coco Rip", "https://cocorip.net", "es"),
|
||||||
SingleLang("Coffee Manga", "https://coffeemanga.io", "en", isNsfw = false, overrideVersionCode = 2),
|
SingleLang("Coffee Manga", "https://coffeemanga.io", "en", isNsfw = false, overrideVersionCode = 2),
|
||||||
|
@ -193,7 +192,7 @@ class MadaraGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("Lolicon", "https://lolicon.mobi", "en", isNsfw = true, overrideVersionCode = 2),
|
SingleLang("Lolicon", "https://lolicon.mobi", "en", isNsfw = true, overrideVersionCode = 2),
|
||||||
SingleLang("Lord Manga", "https://lordmanga.com", "en"),
|
SingleLang("Lord Manga", "https://lordmanga.com", "en"),
|
||||||
SingleLang("Luffy Manga", "https://luffymanga.com", "en", isNsfw = false),
|
SingleLang("Luffy Manga", "https://luffymanga.com", "en", isNsfw = false),
|
||||||
SingleLang("LuxManga", "https://luxmanga.com", "en"),
|
SingleLang("LuxManga", "https://luxmanga.net", "en", isNsfw = true, overrideVersionCode = 1),
|
||||||
SingleLang("MadaraDex", "https://madaradex.org", "en", isNsfw = true, overrideVersionCode = 1),
|
SingleLang("MadaraDex", "https://madaradex.org", "en", isNsfw = true, overrideVersionCode = 1),
|
||||||
SingleLang("Maid Scan", "https://maidscan.com.br", "pt-BR"),
|
SingleLang("Maid Scan", "https://maidscan.com.br", "pt-BR"),
|
||||||
SingleLang("Manga 18h", "https://manga18h.com", "en", isNsfw = true),
|
SingleLang("Manga 18h", "https://manga18h.com", "en", isNsfw = true),
|
||||||
|
@ -214,23 +213,22 @@ class MadaraGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("Manga Lord", "https://mangalord.com", "en", overrideVersionCode = 1),
|
SingleLang("Manga Lord", "https://mangalord.com", "en", overrideVersionCode = 1),
|
||||||
SingleLang("Manga Mammy", "https://mangamammy.ru", "ru", isNsfw = true),
|
SingleLang("Manga Mammy", "https://mangamammy.ru", "ru", isNsfw = true),
|
||||||
SingleLang("Manga Mitsu", "https://mangamitsu.com", "en", isNsfw = true, overrideVersionCode = 2),
|
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 Nerds", "https://manganerds.com", "en", isNsfw = false),
|
||||||
SingleLang("Manga One Love", "https://mangaonelove.site/", "ru", isNsfw = true),
|
SingleLang("Manga One Love", "https://mangaonelove.site/", "ru", isNsfw = true),
|
||||||
SingleLang("Manga Online Team", "https://mangaonlineteam.com", "en"),
|
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.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.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 Read", "https://mangaread.co", "en", overrideVersionCode = 1),
|
||||||
SingleLang("Manga Rock Team", "https://mangarockteam.com", "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 Rock.team (unoriginal)", "https://mangarock.team", "en", isNsfw = false, className = "MangaRockTeamUnoriginal"),
|
||||||
SingleLang("Manga Rocky", "https://mangarocky.com", "en", overrideVersionCode = 1),
|
SingleLang("Manga Rocky", "https://mangarocky.com", "en", overrideVersionCode = 1),
|
||||||
SingleLang("Manga Rose", "https://mangarose.net", "ar"),
|
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 Starz", "https://mangastarz.org", "ar", overrideVersionCode = 5),
|
||||||
SingleLang("Manga Too", "https://mangatoo.com", "en", overrideVersionCode = 1),
|
SingleLang("Manga Too", "https://mangatoo.com", "en", overrideVersionCode = 1),
|
||||||
SingleLang("Manga Tx.gg (unoriginal)", "https://mangatx.gg", "en", isNsfw = false, className = "MangaTxGg"),
|
SingleLang("Manga Tx.gg (unoriginal)", "https://mangatx.gg", "en", isNsfw = false, className = "MangaTxGg"),
|
||||||
SingleLang("Manga Weebs", "https://mangaweebs.in", "en", overrideVersionCode = 8),
|
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-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-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"),
|
SingleLang("Manga-Raw.info (unoriginal)", "https://manga-raw.info", "en", isNsfw = true, className = "MangaRawInfo"),
|
||||||
|
@ -244,8 +242,8 @@ class MadaraGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("MangaBaz", "https://mangabaz.net", "en"),
|
SingleLang("MangaBaz", "https://mangabaz.net", "en"),
|
||||||
SingleLang("MangaBob", "https://mangabob.com", "en", overrideVersionCode = 1),
|
SingleLang("MangaBob", "https://mangabob.com", "en", overrideVersionCode = 1),
|
||||||
SingleLang("MangaCC", "https://mangacc.com", "en"),
|
SingleLang("MangaCC", "https://mangacc.com", "en"),
|
||||||
SingleLang("MangaClash.tv (unoriginal)", "https://mangaclash.tv", "en", isNsfw = true, className = "MangaClashTv"),
|
|
||||||
SingleLang("MangaClash", "https://mangaclash.com", "en", overrideVersionCode = 3),
|
SingleLang("MangaClash", "https://mangaclash.com", "en", overrideVersionCode = 3),
|
||||||
|
SingleLang("MangaClash.tv (unoriginal)", "https://mangaclash.tv", "en", isNsfw = true, className = "MangaClashTv"),
|
||||||
SingleLang("MangaCrazy", "https://mangacrazy.net", "all", isNsfw = true),
|
SingleLang("MangaCrazy", "https://mangacrazy.net", "all", isNsfw = true),
|
||||||
SingleLang("MangaCultivator", "https://mangacultivator.com", "en", overrideVersionCode = 2),
|
SingleLang("MangaCultivator", "https://mangacultivator.com", "en", overrideVersionCode = 2),
|
||||||
SingleLang("MangaCV", "https://mangacv.com", "en", isNsfw = true),
|
SingleLang("MangaCV", "https://mangacv.com", "en", isNsfw = true),
|
||||||
|
@ -287,7 +285,7 @@ class MadaraGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("MangaRosie", "https://mangarosie.in", "en", isNsfw = true),
|
SingleLang("MangaRosie", "https://mangarosie.in", "en", isNsfw = true),
|
||||||
SingleLang("MangaRuby.com", "https://mangaruby.com", "en", isNsfw = true, className = "MangaRubyCom"),
|
SingleLang("MangaRuby.com", "https://mangaruby.com", "en", isNsfw = true, className = "MangaRubyCom"),
|
||||||
SingleLang("Mangaryu", "https://mangaryu.com", "en", isNsfw = true),
|
SingleLang("Mangaryu", "https://mangaryu.com", "en", isNsfw = true),
|
||||||
SingleLang("Mangas No Sekai", "https://mangasnosekai.com", "es", overrideVersionCode = 1),
|
SingleLang("Mangas No Sekai", "https://mangasnosekai.com", "es", overrideVersionCode = 2),
|
||||||
SingleLang("Mangas Origines", "https://mangas-origines.xyz", "fr", isNsfw = true, overrideVersionCode = 4),
|
SingleLang("Mangas Origines", "https://mangas-origines.xyz", "fr", isNsfw = true, overrideVersionCode = 4),
|
||||||
SingleLang("Mangas-Origines.fr", "https://mangas-origines.fr", "fr", className = "MangasOriginesFr"),
|
SingleLang("Mangas-Origines.fr", "https://mangas-origines.fr", "fr", className = "MangasOriginesFr"),
|
||||||
SingleLang("MangaSco", "https://manhwasco.net", "en", overrideVersionCode = 2),
|
SingleLang("MangaSco", "https://manhwasco.net", "en", overrideVersionCode = 2),
|
||||||
|
@ -307,6 +305,7 @@ class MadaraGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("Mangaxico", "https://mangaxico.com", "es", isNsfw = true),
|
SingleLang("Mangaxico", "https://mangaxico.com", "es", isNsfw = true),
|
||||||
SingleLang("MangaXP", "https://mangaxp.com", "en", overrideVersionCode = 1),
|
SingleLang("MangaXP", "https://mangaxp.com", "en", overrideVersionCode = 1),
|
||||||
SingleLang("MangaYami", "https://www.mangayami.club", "en", overrideVersionCode = 2),
|
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("Manhastro", "https://manhastro.com", "pt-BR"),
|
||||||
SingleLang("Manhatic", "https://manhatic.com", "ar", isNsfw = true),
|
SingleLang("Manhatic", "https://manhatic.com", "ar", isNsfw = true),
|
||||||
SingleLang("Manhua ES", "https://manhuaes.com", "en", overrideVersionCode = 6),
|
SingleLang("Manhua ES", "https://manhuaes.com", "en", overrideVersionCode = 6),
|
||||||
|
@ -319,12 +318,12 @@ class MadaraGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("ManhuaBox", "https://manhuabox.net", "en", overrideVersionCode = 2),
|
SingleLang("ManhuaBox", "https://manhuabox.net", "en", overrideVersionCode = 2),
|
||||||
SingleLang("ManhuaChill", "https://manhuachill.com", "en"),
|
SingleLang("ManhuaChill", "https://manhuachill.com", "en"),
|
||||||
SingleLang("ManhuaDex", "https://manhuadex.com", "en", isNsfw = false),
|
SingleLang("ManhuaDex", "https://manhuadex.com", "en", isNsfw = false),
|
||||||
SingleLang("ManhuaFast.net (unoriginal)", "https://manhuafast.net", "en", isNsfw = false, className = "ManhuaFastNet"),
|
|
||||||
SingleLang("ManhuaFast", "https://manhuafast.com", "en", overrideVersionCode = 3),
|
SingleLang("ManhuaFast", "https://manhuafast.com", "en", overrideVersionCode = 3),
|
||||||
|
SingleLang("ManhuaFast.net (unoriginal)", "https://manhuafast.net", "en", isNsfw = false, className = "ManhuaFastNet"),
|
||||||
SingleLang("Manhuaga", "https://manhuaga.com", "en", overrideVersionCode = 2),
|
SingleLang("Manhuaga", "https://manhuaga.com", "en", overrideVersionCode = 2),
|
||||||
SingleLang("ManhuaHot", "https://manhuahot.com", "en"),
|
SingleLang("ManhuaHot", "https://manhuahot.com", "en"),
|
||||||
SingleLang("ManhuaManhwa.online", "https://manhuamanhwa.online", "en", isNsfw = false, className = "ManhuaManhwaOnline"),
|
|
||||||
SingleLang("ManhuaManhwa", "https://manhuamanhwa.com", "en", isNsfw = true),
|
SingleLang("ManhuaManhwa", "https://manhuamanhwa.com", "en", isNsfw = true),
|
||||||
|
SingleLang("ManhuaManhwa.online", "https://manhuamanhwa.online", "en", isNsfw = false, className = "ManhuaManhwaOnline"),
|
||||||
SingleLang("ManhuaScan.info (unoriginal)", "https://manhuascan.info", "en", isNsfw = true, className = "ManhuaScanInfo"),
|
SingleLang("ManhuaScan.info (unoriginal)", "https://manhuascan.info", "en", isNsfw = true, className = "ManhuaScanInfo"),
|
||||||
SingleLang("ManhuaUS", "https://manhuaus.com", "en", overrideVersionCode = 5),
|
SingleLang("ManhuaUS", "https://manhuaus.com", "en", overrideVersionCode = 5),
|
||||||
SingleLang("ManhuaZone", "https://manhuazone.org", "en", overrideVersionCode = 1),
|
SingleLang("ManhuaZone", "https://manhuazone.org", "en", overrideVersionCode = 1),
|
||||||
|
@ -349,8 +348,8 @@ class MadaraGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("Mantraz Scan", "https://mantrazscan.com", "es"),
|
SingleLang("Mantraz Scan", "https://mantrazscan.com", "es"),
|
||||||
SingleLang("ManWe", "https://manwe.pro", "tr", className = "EvaScans", overrideVersionCode = 1),
|
SingleLang("ManWe", "https://manwe.pro", "tr", className = "EvaScans", overrideVersionCode = 1),
|
||||||
SingleLang("ManyComic", "https://manycomic.com", "en", isNsfw = true, overrideVersionCode = 1),
|
SingleLang("ManyComic", "https://manycomic.com", "en", isNsfw = true, overrideVersionCode = 1),
|
||||||
SingleLang("ManyToon.me", "https://manytoon.me", "en", isNsfw = true, className = "ManyToonMe", overrideVersionCode = 5),
|
|
||||||
SingleLang("ManyToon", "https://manytoon.com", "en", isNsfw = true, overrideVersionCode = 5),
|
SingleLang("ManyToon", "https://manytoon.com", "en", isNsfw = true, overrideVersionCode = 5),
|
||||||
|
SingleLang("ManyToon.me", "https://manytoon.me", "en", isNsfw = true, className = "ManyToonMe", overrideVersionCode = 5),
|
||||||
SingleLang("ManyToonClub", "https://manytoon.club", "ko", isNsfw = true, overrideVersionCode = 2),
|
SingleLang("ManyToonClub", "https://manytoon.club", "ko", isNsfw = true, overrideVersionCode = 2),
|
||||||
SingleLang("MG Komik", "https://mgkomik.id", "id", overrideVersionCode = 11),
|
SingleLang("MG Komik", "https://mgkomik.id", "id", overrideVersionCode = 11),
|
||||||
SingleLang("Midnight Mess Scans", "https://midnightmess.org", "en", isNsfw = true, overrideVersionCode = 6),
|
SingleLang("Midnight Mess Scans", "https://midnightmess.org", "en", isNsfw = true, overrideVersionCode = 6),
|
||||||
|
@ -372,9 +371,11 @@ class MadaraGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("NekoPost.co (unoriginal)", "https://www.nekopost.co", "th", isNsfw = false, className = "NekoPostCo"),
|
SingleLang("NekoPost.co (unoriginal)", "https://www.nekopost.co", "th", isNsfw = false, className = "NekoPostCo"),
|
||||||
SingleLang("NekoScan", "https://nekoscan.com", "en", overrideVersionCode = 2),
|
SingleLang("NekoScan", "https://nekoscan.com", "en", overrideVersionCode = 2),
|
||||||
SingleLang("NewManhua", "https://newmanhua.com", "en", isNsfw = true),
|
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("Night Comic", "https://www.nightcomic.com", "en", overrideVersionCode = 1),
|
||||||
SingleLang("Niji Translations", "https://niji-translations.com", "ar", overrideVersionCode = 1),
|
SingleLang("Niji Translations", "https://niji-translations.com", "ar", overrideVersionCode = 1),
|
||||||
SingleLang("Nitro Manga", "https://nitromanga.com", "en", className = "NitroScans", 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("No Index Scan", "https://noindexscan.com", "pt-BR", isNsfw = true),
|
||||||
SingleLang("Noblesse Translations", "https://www.noblessev1.com", "es", overrideVersionCode = 2),
|
SingleLang("Noblesse Translations", "https://www.noblessev1.com", "es", overrideVersionCode = 2),
|
||||||
SingleLang("Nocturne Summer", "https://nocsummer.com.br", "pt-BR", isNsfw = true),
|
SingleLang("Nocturne Summer", "https://nocsummer.com.br", "pt-BR", isNsfw = true),
|
||||||
|
@ -453,6 +454,7 @@ class MadaraGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("Tatakae Scan", "https://tatakaescan.com", "pt-BR", isNsfw = true, overrideVersionCode = 2),
|
SingleLang("Tatakae Scan", "https://tatakaescan.com", "pt-BR", isNsfw = true, overrideVersionCode = 2),
|
||||||
SingleLang("Taurus Fansub", "https://taurusmanga.com", "es", overrideVersionCode = 1),
|
SingleLang("Taurus Fansub", "https://taurusmanga.com", "es", overrideVersionCode = 1),
|
||||||
SingleLang("TeenManhua", "https://teenmanhua.com", "en", 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 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 Blank Scanlation", "https://theblank.net", "en", className = "TheBlank", isNsfw = true),
|
||||||
SingleLang("The Guild", "https://theguildscans.com", "en"),
|
SingleLang("The Guild", "https://theguildscans.com", "en"),
|
||||||
|
@ -502,18 +504,19 @@ class MadaraGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("Yuri Verso", "https://yuri.live", "pt-BR", overrideVersionCode = 3),
|
SingleLang("Yuri Verso", "https://yuri.live", "pt-BR", overrideVersionCode = 3),
|
||||||
SingleLang("Zandy no Fansub", "https://zandynofansub.aishiteru.org", "en"),
|
SingleLang("Zandy no Fansub", "https://zandynofansub.aishiteru.org", "en"),
|
||||||
SingleLang("ZinChanManga", "https://zinchanmanga.com", "en", isNsfw = true),
|
SingleLang("ZinChanManga", "https://zinchanmanga.com", "en", isNsfw = true),
|
||||||
SingleLang("ZinManga.top (unoriginal)", "https://zinmanga.top", "en", isNsfw = false, className = "ZinMangaTop"),
|
|
||||||
SingleLang("Zinmanga", "https://zinmanga.com", "en", overrideVersionCode = 1),
|
SingleLang("Zinmanga", "https://zinmanga.com", "en", overrideVersionCode = 1),
|
||||||
|
SingleLang("ZinManga.top (unoriginal)", "https://zinmanga.top", "en", isNsfw = false, className = "ZinMangaTop"),
|
||||||
SingleLang("Zinmanhwa", "https://zinmanhwa.com", "en"),
|
SingleLang("Zinmanhwa", "https://zinmanhwa.com", "en"),
|
||||||
SingleLang("ZuttoManga", "https://zuttomanga.com", "en", overrideVersionCode = 1),
|
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://manga.detectiveconanar.com", "ar", className = "DetectiveConanAr", overrideVersionCode = 2),
|
||||||
SingleLang("عرب تونز", "https://arabtoons.net", "ar", isNsfw = true, className = "ArabToons"),
|
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://3asq.org", "ar", className = "Manga3asq", overrideVersionCode = 2),
|
||||||
SingleLang("مانجا ليك", "https://manga-lek.net", "ar", className = "Mangalek", overrideVersionCode = 4),
|
SingleLang("مانجا ليك", "https://manga-lek.net", "ar", className = "Mangalek", overrideVersionCode = 4),
|
||||||
SingleLang("مانجا ليكس", "https://mangaleks.com", "ar", className = "MangaLeks"),
|
SingleLang("مانجا ليكس", "https://mangaleks.com", "ar", className = "MangaLeks"),
|
||||||
SingleLang("مانجا لينك", "https://mangalink.io", "ar", className = "MangaLinkio", overrideVersionCode = 3),
|
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"),
|
SingleLang("巴卡漫画", "https://bakamh.com", "zh", isNsfw = true, className = "Bakamh"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -277,7 +277,7 @@ abstract class MadTheme(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String =
|
override fun imageUrlParse(document: Document): String =
|
||||||
throw UnsupportedOperationException("Not used.")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Date logic lifted from Madara
|
// Date logic lifted from Madara
|
||||||
private fun parseChapterDate(date: String?): Long {
|
private fun parseChapterDate(date: String?): Long {
|
||||||
|
|
|
@ -269,7 +269,7 @@ abstract class MangaBox(
|
||||||
return GET(page.imageUrl!!, headersBuilder().set("Referer", page.url).build())
|
return GET(page.imageUrl!!, headersBuilder().set("Referer", page.url).build())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Based on change_alias JS function from Mangakakalot's website
|
// Based on change_alias JS function from Mangakakalot's website
|
||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
|
|
|
@ -36,16 +36,16 @@ abstract class MangaCatalog(
|
||||||
title = name
|
title = name
|
||||||
url = sourceurl
|
url = sourceurl
|
||||||
}
|
}
|
||||||
override fun popularMangaRequest(page: Int): Request = throw Exception("Not used")
|
override fun popularMangaRequest(page: Int): Request = throw UnsupportedOperationException()
|
||||||
override fun popularMangaNextPageSelector(): String? = throw Exception("Not used")
|
override fun popularMangaNextPageSelector(): String? = throw UnsupportedOperationException()
|
||||||
override fun popularMangaSelector(): String = throw Exception("Not used")
|
override fun popularMangaSelector(): String = throw UnsupportedOperationException()
|
||||||
override fun popularMangaFromElement(element: Element) = throw Exception("Not used")
|
override fun popularMangaFromElement(element: Element) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Latest
|
// Latest
|
||||||
override fun latestUpdatesRequest(page: Int): Request = throw Exception("Not used")
|
override fun latestUpdatesRequest(page: Int): Request = throw UnsupportedOperationException()
|
||||||
override fun latestUpdatesNextPageSelector(): String? = throw Exception("Not used")
|
override fun latestUpdatesNextPageSelector(): String? = throw UnsupportedOperationException()
|
||||||
override fun latestUpdatesSelector(): String = throw Exception("Not used")
|
override fun latestUpdatesSelector(): String = throw UnsupportedOperationException()
|
||||||
override fun latestUpdatesFromElement(element: Element): SManga = throw Exception("Not used")
|
override fun latestUpdatesFromElement(element: Element): SManga = throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Search
|
// Search
|
||||||
|
|
||||||
|
@ -59,10 +59,10 @@ abstract class MangaCatalog(
|
||||||
return Observable.just(MangasPage(mangas, false))
|
return Observable.just(MangasPage(mangas, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = throw Exception("Not used")
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = throw UnsupportedOperationException()
|
||||||
override fun searchMangaNextPageSelector() = throw Exception("Not used")
|
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException()
|
||||||
override fun searchMangaSelector() = throw Exception("Not used")
|
override fun searchMangaSelector() = throw UnsupportedOperationException()
|
||||||
override fun searchMangaFromElement(element: Element) = throw Exception("Not used")
|
override fun searchMangaFromElement(element: Element) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Get Override
|
// Get Override
|
||||||
|
|
||||||
|
@ -106,5 +106,5 @@ abstract class MangaCatalog(
|
||||||
Page(index, "", img.attr("src"))
|
Page(index, "", img.attr("src"))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String = throw Exception("Not Used")
|
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,7 @@ abstract class MangAdventure(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response) =
|
override fun imageUrlParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun getMangaUrl(manga: SManga) = "$baseUrl/reader/${manga.url}"
|
override fun getMangaUrl(manga: SManga) = "$baseUrl/reader/${manga.url}"
|
||||||
|
|
||||||
|
|
|
@ -279,7 +279,7 @@ abstract class MangaHub(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chapterFromElement(element: Element): SChapter {
|
override fun chapterFromElement(element: Element): SChapter {
|
||||||
throw UnsupportedOperationException("Not Used")
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseChapterDate(date: String): Long {
|
private fun parseChapterDate(date: String): Long {
|
||||||
|
@ -361,7 +361,7 @@ abstract class MangaHub(
|
||||||
.doOnError { refreshApiKey(chapter) }
|
.doOnError { refreshApiKey(chapter) }
|
||||||
.retry(1)
|
.retry(1)
|
||||||
|
|
||||||
override fun pageListParse(document: Document): List<Page> = throw UnsupportedOperationException("Not used")
|
override fun pageListParse(document: Document): List<Page> = throw UnsupportedOperationException()
|
||||||
override fun pageListParse(response: Response): List<Page> {
|
override fun pageListParse(response: Response): List<Page> {
|
||||||
val chapterObject = json.decodeFromString<ApiChapterPagesResponse>(response.body.string())
|
val chapterObject = json.decodeFromString<ApiChapterPagesResponse>(response.body.string())
|
||||||
|
|
||||||
|
@ -393,7 +393,7 @@ abstract class MangaHub(
|
||||||
return GET(page.url, newHeaders)
|
return GET(page.url, newHeaders)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
|
||||||
|
|
||||||
// filters
|
// filters
|
||||||
private class Genre(title: String, val key: String) : Filter.TriState(title) {
|
private class Genre(title: String, val key: String) : Filter.TriState(title) {
|
||||||
|
|
|
@ -78,5 +78,5 @@ abstract class MangaRawTheme(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used.")
|
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
|
@ -503,15 +503,15 @@ abstract class MangaThemesia(
|
||||||
protected open fun Elements.imgAttr(): String = this.first()!!.imgAttr()
|
protected open fun Elements.imgAttr(): String = this.first()!!.imgAttr()
|
||||||
|
|
||||||
// Unused
|
// Unused
|
||||||
override fun popularMangaSelector(): String = throw UnsupportedOperationException("Not used")
|
override fun popularMangaSelector(): String = throw UnsupportedOperationException()
|
||||||
override fun popularMangaFromElement(element: Element): SManga = throw UnsupportedOperationException("Not used")
|
override fun popularMangaFromElement(element: Element): SManga = throw UnsupportedOperationException()
|
||||||
override fun popularMangaNextPageSelector(): String? = throw UnsupportedOperationException("Not used")
|
override fun popularMangaNextPageSelector(): String? = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun latestUpdatesSelector(): String = throw UnsupportedOperationException("Not used")
|
override fun latestUpdatesSelector(): String = throw UnsupportedOperationException()
|
||||||
override fun latestUpdatesFromElement(element: Element): SManga = throw UnsupportedOperationException("Not used")
|
override fun latestUpdatesFromElement(element: Element): SManga = throw UnsupportedOperationException()
|
||||||
override fun latestUpdatesNextPageSelector(): String? = throw UnsupportedOperationException("Not used")
|
override fun latestUpdatesNextPageSelector(): String? = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not Used")
|
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||||
addRandomUAPreferenceToScreen(screen)
|
addRandomUAPreferenceToScreen(screen)
|
||||||
|
|
|
@ -30,7 +30,7 @@ class MangaThemesiaGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("Berserker Scan", "https://ragnascan.com", "es"),
|
SingleLang("Berserker Scan", "https://ragnascan.com", "es"),
|
||||||
SingleLang("BirdManga", "https://birdmanga.com", "en"),
|
SingleLang("BirdManga", "https://birdmanga.com", "en"),
|
||||||
SingleLang("Boosei", "https://boosei.net", "id", overrideVersionCode = 2),
|
SingleLang("Boosei", "https://boosei.net", "id", overrideVersionCode = 2),
|
||||||
SingleLang("Cartel de Manhwas", "https://carteldemanhwas.com", "es", overrideVersionCode = 5),
|
SingleLang("Cartel de Manhwas", "https://carteldemanhwas.com", "es", overrideVersionCode = 6),
|
||||||
SingleLang("Constellar Scans", "https://constellarcomic.com", "en", isNsfw = true, overrideVersionCode = 16),
|
SingleLang("Constellar Scans", "https://constellarcomic.com", "en", isNsfw = true, overrideVersionCode = 16),
|
||||||
SingleLang("Cosmic Scans", "https://cosmic-scans.com", "en", overrideVersionCode = 2),
|
SingleLang("Cosmic Scans", "https://cosmic-scans.com", "en", overrideVersionCode = 2),
|
||||||
SingleLang("CosmicScans.id", "https://cosmicscans.id", "id", overrideVersionCode = 3, className = "CosmicScansID"),
|
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("KomikIndo.co", "https://komikindo.co", "id", className = "KomikindoCo", overrideVersionCode = 3),
|
||||||
SingleLang("KomikMama", "https://komikmama.co", "id", overrideVersionCode = 1),
|
SingleLang("KomikMama", "https://komikmama.co", "id", overrideVersionCode = 1),
|
||||||
SingleLang("KomikManhwa", "https://komikmanhwa.me", "id", isNsfw = true),
|
SingleLang("KomikManhwa", "https://komikmanhwa.me", "id", isNsfw = true),
|
||||||
SingleLang("Komiktap", "https://komiktap.me", "id", isNsfw = true),
|
|
||||||
SingleLang("Komiksan", "https://komiksan.link", "id", overrideVersionCode = 2),
|
SingleLang("Komiksan", "https://komiksan.link", "id", overrideVersionCode = 2),
|
||||||
|
SingleLang("Komiktap", "https://komiktap.me", "id", isNsfw = true),
|
||||||
SingleLang("Komiku.com", "https://komiku.com", "id", className = "KomikuCom"),
|
SingleLang("Komiku.com", "https://komiku.com", "id", className = "KomikuCom"),
|
||||||
SingleLang("Kuma Scans (Kuma Translation)", "https://kumascans.com", "en", className = "KumaScans", overrideVersionCode = 1),
|
SingleLang("Kuma Scans (Kuma Translation)", "https://kumascans.com", "en", className = "KumaScans", overrideVersionCode = 1),
|
||||||
SingleLang("KumaPoi", "https://kumapoi.info", "id", isNsfw = true, overrideVersionCode = 3),
|
SingleLang("KumaPoi", "https://kumapoi.info", "id", isNsfw = true, overrideVersionCode = 3),
|
||||||
|
@ -86,7 +86,6 @@ class MangaThemesiaGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("Mangacim", "https://www.mangacim.com", "tr", overrideVersionCode = 1),
|
SingleLang("Mangacim", "https://www.mangacim.com", "tr", overrideVersionCode = 1),
|
||||||
SingleLang("MangaKita", "https://mangakita.id", "id", overrideVersionCode = 2),
|
SingleLang("MangaKita", "https://mangakita.id", "id", overrideVersionCode = 2),
|
||||||
SingleLang("Mangakyo", "https://mangakyo.org", "id", overrideVersionCode = 3),
|
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("MangaShiina", "https://mangashiina.com", "es"),
|
||||||
SingleLang("MangaShiro", "https://mangashiro.me", "id"),
|
SingleLang("MangaShiro", "https://mangashiro.me", "id"),
|
||||||
SingleLang("Mangasusu", "https://mangasusuku.xyz", "id", isNsfw = true, overrideVersionCode = 3),
|
SingleLang("Mangasusu", "https://mangasusuku.xyz", "id", isNsfw = true, overrideVersionCode = 3),
|
||||||
|
@ -94,6 +93,7 @@ class MangaThemesiaGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("MangaTale", "https://mangatale.co", "id", overrideVersionCode = 1),
|
SingleLang("MangaTale", "https://mangatale.co", "id", overrideVersionCode = 1),
|
||||||
SingleLang("MangaWT", "https://mangawt.com", "tr", overrideVersionCode = 5),
|
SingleLang("MangaWT", "https://mangawt.com", "tr", overrideVersionCode = 5),
|
||||||
SingleLang("Mangayaro", "https://www.mangayaro.id", "id", overrideVersionCode = 1),
|
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("Mangás Online", "https://mangasonline.cc", "pt-BR", className = "MangasOnline"),
|
||||||
SingleLang("Manhwa Freak", "https://manhwa-freak.com", "en", overrideVersionCode = 3),
|
SingleLang("Manhwa Freak", "https://manhwa-freak.com", "en", overrideVersionCode = 3),
|
||||||
SingleLang("Manhwa Lover", "https://manhwalover.com", "en", isNsfw = true, overrideVersionCode = 1),
|
SingleLang("Manhwa Lover", "https://manhwalover.com", "en", isNsfw = true, overrideVersionCode = 1),
|
||||||
|
@ -137,6 +137,7 @@ class MangaThemesiaGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("Senpai Ediciones", "http://senpaiediciones.com", "es", overrideVersionCode = 1),
|
SingleLang("Senpai Ediciones", "http://senpaiediciones.com", "es", overrideVersionCode = 1),
|
||||||
SingleLang("Shadow Mangas", "https://shadowmangas.com", "es", overrideVersionCode = 1),
|
SingleLang("Shadow Mangas", "https://shadowmangas.com", "es", overrideVersionCode = 1),
|
||||||
SingleLang("Shea Manga", "https://sheakomik.com", "id", overrideVersionCode = 4),
|
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("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("Siren Komik", "https://sirenkomik.my.id", "id", className = "MangKomik", overrideVersionCode = 2),
|
||||||
SingleLang("SkyMangas", "https://skymangas.com", "es", overrideVersionCode = 1),
|
SingleLang("SkyMangas", "https://skymangas.com", "es", overrideVersionCode = 1),
|
||||||
|
@ -152,7 +153,6 @@ class MangaThemesiaGenerator : ThemeSourceGenerator {
|
||||||
SingleLang("Sushiscan.fr", "https://anime-sama.me", "fr", className = "SushiScanFR", overrideVersionCode = 1),
|
SingleLang("Sushiscan.fr", "https://anime-sama.me", "fr", className = "SushiScanFR", overrideVersionCode = 1),
|
||||||
SingleLang("Tarot Scans", "https://www.tarotscans.com", "tr"),
|
SingleLang("Tarot Scans", "https://www.tarotscans.com", "tr"),
|
||||||
SingleLang("Tecno Scan", "https://tecnoscann.com", "es", isNsfw = true, overrideVersionCode = 6),
|
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("Tenshi.id", "https://tenshi.id", "id", className = "TenshiId", pkgName = "masterkomik", overrideVersionCode = 4),
|
||||||
SingleLang("The Apollo Team", "https://theapollo.team", "en"),
|
SingleLang("The Apollo Team", "https://theapollo.team", "en"),
|
||||||
SingleLang("Tres Daos Scan", "https://tresdaos.com", "es"),
|
SingleLang("Tres Daos Scan", "https://tresdaos.com", "es"),
|
||||||
|
|
|
@ -201,7 +201,7 @@ abstract class MangaWorld(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used.")
|
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun imageRequest(page: Page): Request {
|
override fun imageRequest(page: Page): Request {
|
||||||
val imgHeader = Headers.Builder().apply {
|
val imgHeader = Headers.Builder().apply {
|
||||||
|
|
|
@ -96,7 +96,7 @@ open class MCCMS(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mangaDetailsParse(response: Response): SManga = throw UnsupportedOperationException("Not used.")
|
override fun mangaDetailsParse(response: Response): SManga = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> = Observable.fromCallable {
|
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> = Observable.fromCallable {
|
||||||
val id = getMangaId(manga.url)
|
val id = getMangaId(manga.url)
|
||||||
|
@ -112,7 +112,7 @@ open class MCCMS(
|
||||||
|
|
||||||
protected open fun getMangaId(url: String) = url.substringAfterLast('/')
|
protected open fun getMangaId(url: String) = url.substringAfterLast('/')
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> = throw UnsupportedOperationException("Not used.")
|
override fun chapterListParse(response: Response): List<SChapter> = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun pageListRequest(chapter: SChapter): Request =
|
override fun pageListRequest(chapter: SChapter): Request =
|
||||||
GET(baseUrl + chapter.url, pcHeaders)
|
GET(baseUrl + chapter.url, pcHeaders)
|
||||||
|
@ -126,7 +126,7 @@ open class MCCMS(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Not used.")
|
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun imageRequest(page: Page) = GET(page.imageUrl!!, pcHeaders)
|
override fun imageRequest(page: Page) = GET(page.imageUrl!!, pcHeaders)
|
||||||
|
|
||||||
|
|
|
@ -420,7 +420,7 @@ abstract class MMRCMS(
|
||||||
Page(i, response.request.url.toString(), url)
|
Page(i, response.request.url.toString(), url)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Unused method called!")
|
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
private fun getInitialFilterList() = listOf<Filter<*>>(
|
private fun getInitialFilterList() = listOf<Filter<*>>(
|
||||||
Filter.Header("NOTE: Ignored if using text search!"),
|
Filter.Header("NOTE: Ignored if using text search!"),
|
||||||
|
|
|
@ -107,32 +107,32 @@ open class MonochromeCMS(
|
||||||
json.decodeFromString<T>(body.string())
|
json.decodeFromString<T>(body.string())
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int) =
|
override fun popularMangaRequest(page: Int) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int) =
|
override fun latestUpdatesRequest(page: Int) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun mangaDetailsRequest(manga: SManga) =
|
override fun mangaDetailsRequest(manga: SManga) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun popularMangaParse(response: Response) =
|
override fun popularMangaParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun latestUpdatesParse(response: Response) =
|
override fun latestUpdatesParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun mangaDetailsParse(response: Response) =
|
override fun mangaDetailsParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun chapterListParse(response: Response) =
|
override fun chapterListParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun pageListRequest(chapter: SChapter) =
|
override fun pageListRequest(chapter: SChapter) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun pageListParse(response: Response) =
|
override fun pageListParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response) =
|
override fun imageUrlParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
|
@ -262,7 +262,7 @@ abstract class MyMangaCMS(
|
||||||
|
|
||||||
override fun chapterListSelector(): String = "ul.list-chapters > a"
|
override fun chapterListSelector(): String = "ul.list-chapters > a"
|
||||||
|
|
||||||
override fun chapterFromElement(element: Element): SChapter = throw Exception("Not used")
|
override fun chapterFromElement(element: Element): SChapter = throw UnsupportedOperationException()
|
||||||
|
|
||||||
private fun chapterFromElement(element: Element, scanlator: String?): SChapter =
|
private fun chapterFromElement(element: Element, scanlator: String?): SChapter =
|
||||||
SChapter.create().apply {
|
SChapter.create().apply {
|
||||||
|
@ -307,7 +307,7 @@ abstract class MyMangaCMS(
|
||||||
.filterNot { it.attr("abs:data-src").isNullOrEmpty() }
|
.filterNot { it.attr("abs:data-src").isNullOrEmpty() }
|
||||||
.mapIndexed { index, elem -> Page(index, "", elem.attr("abs:data-src")) }
|
.mapIndexed { index, elem -> Page(index, "", elem.attr("abs:data-src")) }
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String = throw Exception("Not used")
|
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
//region Filters
|
//region Filters
|
||||||
|
|
|
@ -227,7 +227,7 @@ abstract class NepNep(
|
||||||
return parseDirectory(1)
|
return parseDirectory(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun searchMangaParse(response: Response): MangasPage = throw UnsupportedOperationException("Not used")
|
override fun searchMangaParse(response: Response): MangasPage = throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Details
|
// Details
|
||||||
|
|
||||||
|
@ -357,7 +357,7 @@ abstract class NepNep(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Filters
|
// Filters
|
||||||
|
|
||||||
|
|
|
@ -95,9 +95,9 @@ open class OtakuSanctuary(
|
||||||
return MangasPage(parseMangaCollection(collection), hasNextPage)
|
return MangasPage(parseMangaCollection(collection), hasNextPage)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException("Not used")
|
override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun latestUpdatesParse(response: Response) = throw UnsupportedOperationException("Not used")
|
override fun latestUpdatesParse(response: Response) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request =
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request =
|
||||||
GET(
|
GET(
|
||||||
|
@ -176,7 +176,7 @@ open class OtakuSanctuary(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun pageListParse(response: Response): List<Page> {
|
override fun pageListParse(response: Response): List<Page> {
|
||||||
val document = response.asJsoup()
|
val document = response.asJsoup()
|
||||||
|
|
|
@ -130,7 +130,7 @@ abstract class Paprika(
|
||||||
|
|
||||||
// never called
|
// never called
|
||||||
override fun chapterFromElement(element: Element): SChapter {
|
override fun chapterFromElement(element: Element): SChapter {
|
||||||
throw Exception("unreachable code was reached!")
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun chapterFromElement(element: Element, mangaTitle: String): SChapter {
|
open fun chapterFromElement(element: Element, mangaTitle: String): SChapter {
|
||||||
|
@ -179,7 +179,7 @@ abstract class Paprika(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Filters
|
// Filters
|
||||||
|
|
||||||
|
|
|
@ -174,15 +174,15 @@ abstract class ReadAllComics(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document) =
|
override fun imageUrlParse(document: Document) =
|
||||||
throw UnsupportedOperationException("Not Implemented")
|
throw UnsupportedOperationException()
|
||||||
override fun latestUpdatesRequest(page: Int) =
|
override fun latestUpdatesRequest(page: Int) =
|
||||||
throw UnsupportedOperationException("Not Implemented")
|
throw UnsupportedOperationException()
|
||||||
override fun latestUpdatesFromElement(element: Element) =
|
override fun latestUpdatesFromElement(element: Element) =
|
||||||
throw UnsupportedOperationException("Not Implemented")
|
throw UnsupportedOperationException()
|
||||||
override fun latestUpdatesSelector() =
|
override fun latestUpdatesSelector() =
|
||||||
throw UnsupportedOperationException("Not Implemented")
|
throw UnsupportedOperationException()
|
||||||
override fun latestUpdatesNextPageSelector() =
|
override fun latestUpdatesNextPageSelector() =
|
||||||
throw UnsupportedOperationException("Not Implemented")
|
throw UnsupportedOperationException()
|
||||||
override fun popularMangaFromElement(element: Element) =
|
override fun popularMangaFromElement(element: Element) =
|
||||||
throw UnsupportedOperationException("Not Implemented")
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,11 +165,11 @@ abstract class ReaderFront(
|
||||||
private inline val JsonElement.content get() = jsonPrimitive.content
|
private inline val JsonElement.content get() = jsonPrimitive.content
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun searchMangaParse(response: Response) =
|
override fun searchMangaParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response) =
|
override fun imageUrlParse(response: Response) =
|
||||||
throw UnsupportedOperationException("Not used!")
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,7 +261,7 @@ abstract class Senkuro(
|
||||||
chapterListParse(response, manga)
|
chapterListParse(response, manga)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
override fun chapterListParse(response: Response) = throw UnsupportedOperationException("chapterListParse(response: Response, manga: SManga)")
|
override fun chapterListParse(response: Response) = throw UnsupportedOperationException()
|
||||||
private fun chapterListParse(response: Response, manga: SManga): List<SChapter> {
|
private fun chapterListParse(response: Response, manga: SManga): List<SChapter> {
|
||||||
val chaptersList = json.decodeFromString<PageWrapperDto<MangaTachiyomiChaptersDto>>(response.body.string())
|
val chaptersList = json.decodeFromString<PageWrapperDto<MangaTachiyomiChaptersDto>>(response.body.string())
|
||||||
val teamsList = chaptersList.data.mangaTachiyomiChapters.teams
|
val teamsList = chaptersList.data.mangaTachiyomiChapters.teams
|
||||||
|
|
|
@ -215,7 +215,7 @@ abstract class SinMH(
|
||||||
emptyList() // []
|
emptyList() // []
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not Used.")
|
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
|
||||||
|
|
||||||
protected class UriPartFilter(displayName: String, values: Array<String>, private val uriParts: Array<String>) :
|
protected class UriPartFilter(displayName: String, values: Array<String>, private val uriParts: Array<String>) :
|
||||||
Filter.Select<String>(displayName, values) {
|
Filter.Select<String>(displayName, values) {
|
||||||
|
|
|
@ -154,11 +154,11 @@ open class WebtoonsTranslate(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chapterListSelector(): String = throw Exception("Not used")
|
override fun chapterListSelector(): String = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun chapterFromElement(element: Element): SChapter = throw Exception("Not used")
|
override fun chapterFromElement(element: Element): SChapter = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun pageListParse(document: Document): List<Page> = throw Exception("Not used")
|
override fun pageListParse(document: Document): List<Page> = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun chapterListRequest(manga: SManga): Request {
|
override fun chapterListRequest(manga: SManga): Request {
|
||||||
val mangaUrl = manga.url.toHttpUrl()
|
val mangaUrl = manga.url.toHttpUrl()
|
||||||
|
|
|
@ -220,7 +220,7 @@ abstract class WPComics(
|
||||||
.mapIndexed { i, image -> Page(i, "", image) }
|
.mapIndexed { i, image -> Page(i, "", image) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Filters
|
// Filters
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,7 @@ abstract class Zbulu(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Filters
|
// Filters
|
||||||
|
|
||||||
|
|
|
@ -272,7 +272,7 @@ abstract class ZeistManga(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Not used.")
|
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
|
||||||
|
|
||||||
protected open val mangaCategory: String = "Series"
|
protected open val mangaCategory: String = "Series"
|
||||||
|
|
||||||
|
|
|
@ -174,7 +174,7 @@ abstract class ZManga(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
|
||||||
|
|
||||||
open val hasProjectPage = false
|
open val hasProjectPage = false
|
||||||
|
|
||||||
|
|
|
@ -69,10 +69,6 @@ interface ThemeSourceGenerator {
|
||||||
gradle.writeText(
|
gradle.writeText(
|
||||||
"""
|
"""
|
||||||
|// THIS FILE IS AUTO-GENERATED; DO NOT EDIT
|
|// THIS FILE IS AUTO-GENERATED; DO NOT EDIT
|
||||||
|apply plugin: 'com.android.application'
|
|
||||||
|apply plugin: 'kotlin-android'
|
|
||||||
|apply plugin: 'kotlinx-serialization'
|
|
||||||
|
|
|
||||||
|ext {
|
|ext {
|
||||||
| extName = '${source.name}'
|
| extName = '${source.name}'
|
||||||
| pkgNameSuffix = '${pkgNameSuffix(source, ".")}'
|
| pkgNameSuffix = '${pkgNameSuffix(source, ".")}'
|
||||||
|
@ -81,9 +77,11 @@ interface ThemeSourceGenerator {
|
||||||
| extVersionCode = ${baseVersionCode + source.overrideVersionCode + multisrcLibraryVersion}
|
| extVersionCode = ${baseVersionCode + source.overrideVersionCode + multisrcLibraryVersion}
|
||||||
| ${if (source.isNsfw) "isNsfw = true\n" else ""}
|
| ${if (source.isNsfw) "isNsfw = true\n" else ""}
|
||||||
|}
|
|}
|
||||||
|
|
|
||||||
|
|apply from: "${'$'}rootDir/common.gradle"
|
||||||
|
|
|
||||||
|$defaultAdditionalGradleText
|
|$defaultAdditionalGradleText
|
||||||
|$additionalGradleOverrideText
|
|$additionalGradleOverrideText
|
||||||
|apply from: "${'$'}rootDir/common.gradle"
|
|
||||||
|
|
|
|
||||||
|android {
|
|android {
|
||||||
| defaultConfig {
|
| defaultConfig {
|
||||||
|
@ -92,6 +90,7 @@ interface ThemeSourceGenerator {
|
||||||
| ]
|
| ]
|
||||||
| }
|
| }
|
||||||
|}
|
|}
|
||||||
|
|
|
||||||
""".trimMargin(),
|
""".trimMargin(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -109,6 +108,7 @@ interface ThemeSourceGenerator {
|
||||||
|<?xml version="1.0" encoding="utf-8"?>
|
|<?xml version="1.0" encoding="utf-8"?>
|
||||||
|<!-- THIS FILE IS AUTO-GENERATED; DO NOT EDIT -->
|
|<!-- THIS FILE IS AUTO-GENERATED; DO NOT EDIT -->
|
||||||
|<manifest />
|
|<manifest />
|
||||||
|
|
|
||||||
""".trimMargin(),
|
""".trimMargin(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
apply plugin: 'com.android.application'
|
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
extName = 'Akuma'
|
extName = 'Akuma'
|
||||||
pkgNameSuffix = 'all.akuma'
|
pkgNameSuffix = 'all.akuma'
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
apply plugin: 'com.android.application'
|
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
apply plugin: 'kotlinx-serialization'
|
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
extName = 'Bato.to'
|
extName = 'Bato.to'
|
||||||
pkgNameSuffix = 'all.batoto'
|
pkgNameSuffix = 'all.batoto'
|
||||||
|
|
|
@ -298,10 +298,10 @@ open class BatoTo(
|
||||||
add("prevPos", "null")
|
add("prevPos", "null")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = throw UnsupportedOperationException("Not used")
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = throw UnsupportedOperationException()
|
||||||
override fun searchMangaSelector() = throw UnsupportedOperationException("Not used")
|
override fun searchMangaSelector() = throw UnsupportedOperationException()
|
||||||
override fun searchMangaFromElement(element: Element) = throw UnsupportedOperationException("Not used")
|
override fun searchMangaFromElement(element: Element) = throw UnsupportedOperationException()
|
||||||
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException("Not used")
|
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override fun mangaDetailsRequest(manga: SManga): Request {
|
override fun mangaDetailsRequest(manga: SManga): Request {
|
||||||
if (manga.url.startsWith("http")) {
|
if (manga.url.startsWith("http")) {
|
||||||
|
@ -456,7 +456,7 @@ open class BatoTo(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pageListParse(document: Document): List<Page> {
|
override fun pageListParse(document: Document): List<Page> {
|
||||||
val script = document.selectFirst("script:containsData(imgHttpLis):containsData(batoWord):containsData(batoPass)")?.html()
|
val script = document.selectFirst("script:containsData(imgHttps):containsData(batoWord):containsData(batoPass)")?.html()
|
||||||
?: throw RuntimeException("Couldn't find script with image data.")
|
?: throw RuntimeException("Couldn't find script with image data.")
|
||||||
|
|
||||||
val imgHttpsString = script.substringAfter("const imgHttps =").substringBefore(";").trim()
|
val imgHttpsString = script.substringAfter("const imgHttps =").substringBefore(";").trim()
|
||||||
|
@ -473,7 +473,7 @@ open class BatoTo(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
|
||||||
|
|
||||||
private fun String.removeEntities(): String = Parser.unescapeEntities(this, true)
|
private fun String.removeEntities(): String = Parser.unescapeEntities(this, true)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
apply plugin: 'com.android.application'
|
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
extName = 'Buon Dua'
|
extName = 'Buon Dua'
|
||||||
pkgNameSuffix = 'all.buondua'
|
pkgNameSuffix = 'all.buondua'
|
||||||
|
|
|
@ -102,7 +102,7 @@ class BuonDua() : ParsedHttpSource() {
|
||||||
return pages
|
return pages
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")
|
override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException()
|
||||||
|
|
||||||
// Filters
|
// Filters
|
||||||
override fun getFilterList(): FilterList = FilterList(
|
override fun getFilterList(): FilterList = FilterList(
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
apply plugin: 'com.android.application'
|
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
apply plugin: 'kotlinx-serialization'
|
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
extName = 'Comic Fury'
|
extName = 'Comic Fury'
|
||||||
pkgNameSuffix = 'all.comicfury'
|
pkgNameSuffix = 'all.comicfury'
|
||||||
|
@ -10,8 +6,8 @@ ext {
|
||||||
isNsfw = true
|
isNsfw = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apply from: "$rootDir/common.gradle"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(':lib-textinterceptor'))
|
implementation(project(':lib-textinterceptor'))
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
|
||||||
|
|
|
@ -276,7 +276,7 @@ class ComicFury(
|
||||||
override fun latestUpdatesParse(response: Response): MangasPage = searchMangaParse(response)
|
override fun latestUpdatesParse(response: Response): MangasPage = searchMangaParse(response)
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response): String =
|
override fun imageUrlParse(response: Response): String =
|
||||||
throw UnsupportedOperationException("Not Used")
|
throw UnsupportedOperationException()
|
||||||
|
|
||||||
private fun String.toDate(): Long {
|
private fun String.toDate(): Long {
|
||||||
val ret = this.replace("st", "")
|
val ret = this.replace("st", "")
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
apply plugin: 'com.android.application'
|
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
apply plugin: 'kotlinx-serialization'
|
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
extName = 'Comick'
|
extName = 'Comick'
|
||||||
pkgNameSuffix = 'all.comickfun'
|
pkgNameSuffix = 'all.comickfun'
|
||||||
|
@ -10,8 +6,8 @@ ext {
|
||||||
isNsfw = true
|
isNsfw = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apply from: "$rootDir/common.gradle"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":lib-i18n"))
|
implementation(project(":lib-i18n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
|
||||||
|
|
|
@ -452,7 +452,7 @@ abstract class ComickFun(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response): String {
|
override fun imageUrlParse(response: Response): String {
|
||||||
throw UnsupportedOperationException("Not used")
|
throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getFilterList() = getFilters()
|
override fun getFilterList() = getFilters()
|
||||||
|
|