[zh-dmzj]Add fallback api to fetch hidden manga and URL intent filter. (#5624)
This commit is contained in:
parent
bba235621c
commit
b1d483f293
|
@ -1,2 +1,43 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest package="eu.kanade.tachiyomi.extension" />
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="eu.kanade.tachiyomi.extension">
|
||||||
|
|
||||||
|
<application>
|
||||||
|
<activity
|
||||||
|
android:name=".zh.dmzj.DmzjUrlActivity"
|
||||||
|
android:excludeFromRecents="true"
|
||||||
|
android:theme="@android:style/Theme.NoDisplay">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
|
<data
|
||||||
|
android:host="m.dmzj.com"
|
||||||
|
android:pathPattern="/info/..*"
|
||||||
|
android:scheme="https" />
|
||||||
|
<data
|
||||||
|
android:host="www.dmzj.com"
|
||||||
|
android:pathPattern="/info/..*"
|
||||||
|
android:scheme="https" />
|
||||||
|
<data
|
||||||
|
android:host="manhua.dmzj.com"
|
||||||
|
android:pathPattern="/..*"
|
||||||
|
android:scheme="https" />
|
||||||
|
<data
|
||||||
|
android:host="m.dmzj1.com"
|
||||||
|
android:pathPattern="/info/..*"
|
||||||
|
android:scheme="https" />
|
||||||
|
<data
|
||||||
|
android:host="www.dmzj1.com"
|
||||||
|
android:pathPattern="/info/..*"
|
||||||
|
android:scheme="https" />
|
||||||
|
<data
|
||||||
|
android:host="manhua.dmzj1.com"
|
||||||
|
android:pathPattern="/..*"
|
||||||
|
android:scheme="https" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
</manifest>
|
||||||
|
|
|
@ -5,7 +5,7 @@ ext {
|
||||||
extName = 'Dmzj'
|
extName = 'Dmzj'
|
||||||
pkgNameSuffix = 'zh.dmzj'
|
pkgNameSuffix = 'zh.dmzj'
|
||||||
extClass = '.Dmzj'
|
extClass = '.Dmzj'
|
||||||
extVersionCode = 15
|
extVersionCode = 16
|
||||||
libVersion = '1.2'
|
libVersion = '1.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@ import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
|
import okhttp3.Headers
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
|
@ -37,7 +39,9 @@ class Dmzj : ConfigurableSource, HttpSource() {
|
||||||
override val supportsLatest = true
|
override val supportsLatest = true
|
||||||
override val name = "动漫之家"
|
override val name = "动漫之家"
|
||||||
override val baseUrl = "https://m.dmzj1.com"
|
override val baseUrl = "https://m.dmzj1.com"
|
||||||
private val apiUrl = "https://v3api.dmzj1.com"
|
private val v3apiUrl = "https://v3api.dmzj1.com"
|
||||||
|
private val apiUrl = "https://api.dmzj.com"
|
||||||
|
private val oldPageListApiUrl = "https://m.dmzj.com/chapinfo"
|
||||||
private val imageCDNUrl = "https://images.dmzj1.com"
|
private val imageCDNUrl = "https://images.dmzj1.com"
|
||||||
|
|
||||||
private fun cleanUrl(url: String) = if (url.startsWith("//"))
|
private fun cleanUrl(url: String) = if (url.startsWith("//"))
|
||||||
|
@ -48,6 +52,10 @@ class Dmzj : ConfigurableSource, HttpSource() {
|
||||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val v3apiRateLimitInterceptor = SpecificHostRateLimitInterceptor(
|
||||||
|
HttpUrl.parse(v3apiUrl)!!,
|
||||||
|
preferences.getString(API_RATELIMIT_PREF, "5")!!.toInt()
|
||||||
|
)
|
||||||
private val apiRateLimitInterceptor = SpecificHostRateLimitInterceptor(
|
private val apiRateLimitInterceptor = SpecificHostRateLimitInterceptor(
|
||||||
HttpUrl.parse(apiUrl)!!,
|
HttpUrl.parse(apiUrl)!!,
|
||||||
preferences.getString(API_RATELIMIT_PREF, "5")!!.toInt()
|
preferences.getString(API_RATELIMIT_PREF, "5")!!.toInt()
|
||||||
|
@ -59,12 +67,13 @@ class Dmzj : ConfigurableSource, HttpSource() {
|
||||||
|
|
||||||
override val client: OkHttpClient = network.client.newBuilder()
|
override val client: OkHttpClient = network.client.newBuilder()
|
||||||
.addNetworkInterceptor(apiRateLimitInterceptor)
|
.addNetworkInterceptor(apiRateLimitInterceptor)
|
||||||
|
.addNetworkInterceptor(v3apiRateLimitInterceptor)
|
||||||
.addNetworkInterceptor(imageCDNRateLimitInterceptor)
|
.addNetworkInterceptor(imageCDNRateLimitInterceptor)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
private fun myGet(url: String) = GET(url)
|
override fun headersBuilder() = Headers.Builder().apply {
|
||||||
.newBuilder()
|
set("Referer", "https://www.dmzj1.com/")
|
||||||
.header(
|
set(
|
||||||
"User-Agent",
|
"User-Agent",
|
||||||
"Mozilla/5.0 (Linux; Android 10) " +
|
"Mozilla/5.0 (Linux; Android 10) " +
|
||||||
"AppleWebKit/537.36 (KHTML, like Gecko) " +
|
"AppleWebKit/537.36 (KHTML, like Gecko) " +
|
||||||
|
@ -72,7 +81,7 @@ class Dmzj : ConfigurableSource, HttpSource() {
|
||||||
"Mobile Safari/537.36 " +
|
"Mobile Safari/537.36 " +
|
||||||
"Tachiyomi/1.0"
|
"Tachiyomi/1.0"
|
||||||
)
|
)
|
||||||
.build()!!
|
}
|
||||||
|
|
||||||
// for simple searches (query only, no filters)
|
// for simple searches (query only, no filters)
|
||||||
private fun simpleSearchJsonParse(json: String): MangasPage {
|
private fun simpleSearchJsonParse(json: String): MangasPage {
|
||||||
|
@ -117,19 +126,53 @@ class Dmzj : ConfigurableSource, HttpSource() {
|
||||||
return MangasPage(ret, arr.length() != 0)
|
return MangasPage(ret, arr.length() != 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int) = myGet("$apiUrl/classify/0/0/${page - 1}.json")
|
override fun popularMangaRequest(page: Int) = GET("$v3apiUrl/classify/0/0/${page - 1}.json")
|
||||||
|
|
||||||
override fun popularMangaParse(response: Response) = searchMangaParse(response)
|
override fun popularMangaParse(response: Response) = searchMangaParse(response)
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int) = myGet("$apiUrl/classify/0/1/${page - 1}.json")
|
override fun latestUpdatesRequest(page: Int) = GET("$v3apiUrl/classify/0/1/${page - 1}.json")
|
||||||
|
|
||||||
override fun latestUpdatesParse(response: Response): MangasPage = searchMangaParse(response)
|
override fun latestUpdatesParse(response: Response): MangasPage = searchMangaParse(response)
|
||||||
|
|
||||||
|
private fun searchMangaById(id: String): MangasPage {
|
||||||
|
val comicNumberID = if (checkComicIdIsNumericalRegex.matches(id)) {
|
||||||
|
id
|
||||||
|
} else {
|
||||||
|
val document = client.newCall(GET("$baseUrl/info/$id.html", headers)).execute().asJsoup()
|
||||||
|
extractComicIdFromWebpageRegex.find(document.select("#Subscribe").attr("onclick"))!!.groups[1]!!.value // onclick="addSubscribe('{comicNumberID}')"
|
||||||
|
}
|
||||||
|
|
||||||
|
val sManga = try {
|
||||||
|
val r = client.newCall(GET("$v3apiUrl/comic/comic_$comicNumberID.json", headers)).execute()
|
||||||
|
mangaDetailsParse(r)
|
||||||
|
} catch (_: Exception) {
|
||||||
|
val r = client.newCall(GET("$apiUrl/dynamic/comicinfo/$comicNumberID.json", headers)).execute()
|
||||||
|
mangaDetailsParse(r)
|
||||||
|
}
|
||||||
|
sManga.url = "$baseUrl/info/$comicNumberID.html"
|
||||||
|
|
||||||
|
return MangasPage(listOf(sManga), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
||||||
|
return if (query.startsWith(PREFIX_ID_SEARCH)) {
|
||||||
|
// ID may be numbers or Chinese pinyin
|
||||||
|
val id = query.removePrefix(PREFIX_ID_SEARCH).removeSuffix(".html")
|
||||||
|
Observable.just(searchMangaById(id))
|
||||||
|
} else {
|
||||||
|
client.newCall(searchMangaRequest(page, query, filters))
|
||||||
|
.asObservableSuccess()
|
||||||
|
.map { response ->
|
||||||
|
searchMangaParse(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||||
if (query != "") {
|
if (query != "") {
|
||||||
val uri = Uri.parse("http://s.acg.dmzj1.com/comicsum/search.php").buildUpon()
|
val uri = Uri.parse("http://s.acg.dmzj1.com/comicsum/search.php").buildUpon()
|
||||||
uri.appendQueryParameter("s", query)
|
uri.appendQueryParameter("s", query)
|
||||||
return myGet(uri.toString())
|
return GET(uri.toString())
|
||||||
} else {
|
} else {
|
||||||
var params = filters.map {
|
var params = filters.map {
|
||||||
if (it !is SortFilter && it is UriPartFilter) {
|
if (it !is SortFilter && it is UriPartFilter) {
|
||||||
|
@ -142,7 +185,7 @@ class Dmzj : ConfigurableSource, HttpSource() {
|
||||||
|
|
||||||
val order = filters.filterIsInstance<SortFilter>().joinToString("") { (it as UriPartFilter).toUriPart() }
|
val order = filters.filterIsInstance<SortFilter>().joinToString("") { (it as UriPartFilter).toUriPart() }
|
||||||
|
|
||||||
return myGet("$apiUrl/classify/$params/$order/${page - 1}.json")
|
return GET("$v3apiUrl/classify/$params/$order/${page - 1}.json")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,69 +199,123 @@ class Dmzj : ConfigurableSource, HttpSource() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bypass mangaDetailsRequest, fetch v3api url directly
|
// Bypass mangaDetailsRequest, fetch api url directly
|
||||||
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
|
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
|
||||||
return client.newCall(GET(apiUrl + manga.url, headers))
|
val cid = extractComicIdFromMangaUrlRegex.find(manga.url)!!.groups[1]!!.value
|
||||||
.asObservableSuccess()
|
return try {
|
||||||
.map { response ->
|
// Not using client.newCall().asObservableSuccess() to ensure we can catch exception here.
|
||||||
mangaDetailsParse(response).apply { initialized = true }
|
val response = client.newCall(GET("$v3apiUrl/comic/comic_$cid.json", headers)).execute()
|
||||||
}
|
val sManga = mangaDetailsParse(response).apply { initialized = true }
|
||||||
|
Observable.just(sManga)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
val response = client.newCall(GET("$apiUrl/dynamic/comicinfo/$cid.json", headers)).execute()
|
||||||
|
val sManga = mangaDetailsParse(response).apply { initialized = true }
|
||||||
|
Observable.just(sManga)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Observable.error(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val re1 = Regex("""\d+""") // Get comic ID from manga.url
|
|
||||||
// Workaround to allow "Open in browser" use human readable webpage url.
|
// Workaround to allow "Open in browser" use human readable webpage url.
|
||||||
override fun mangaDetailsRequest(manga: SManga): Request {
|
override fun mangaDetailsRequest(manga: SManga): Request {
|
||||||
return GET("$baseUrl/info/${re1.find(manga.url)!!.value}.html")
|
val cid = extractComicIdFromMangaUrlRegex.find(manga.url)!!.groups[1]!!.value
|
||||||
}
|
return GET("$baseUrl/info/$cid.html")
|
||||||
|
|
||||||
override fun chapterListRequest(manga: SManga): Request {
|
|
||||||
return GET(apiUrl + manga.url, headers)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mangaDetailsParse(response: Response) = SManga.create().apply {
|
override fun mangaDetailsParse(response: Response) = SManga.create().apply {
|
||||||
val obj = JSONObject(response.body()!!.string())
|
val obj = JSONObject(response.body()!!.string())
|
||||||
|
|
||||||
title = obj.getString("title")
|
if (response.request().url().toString().startsWith(v3apiUrl)) {
|
||||||
thumbnail_url = obj.getString("cover")
|
title = obj.getString("title")
|
||||||
|
thumbnail_url = obj.getString("cover")
|
||||||
|
var arr = obj.getJSONArray("authors")
|
||||||
|
val tmparr = ArrayList<String>(arr.length())
|
||||||
|
for (i in 0 until arr.length()) {
|
||||||
|
tmparr.add(arr.getJSONObject(i).getString("tag_name"))
|
||||||
|
}
|
||||||
|
author = tmparr.joinToString(", ")
|
||||||
|
|
||||||
var arr = obj.getJSONArray("authors")
|
arr = obj.getJSONArray("types")
|
||||||
val tmparr = ArrayList<String>(arr.length())
|
tmparr.clear()
|
||||||
for (i in 0 until arr.length()) {
|
for (i in 0 until arr.length()) {
|
||||||
tmparr.add(arr.getJSONObject(i).getString("tag_name"))
|
tmparr.add(arr.getJSONObject(i).getString("tag_name"))
|
||||||
}
|
}
|
||||||
author = tmparr.joinToString(", ")
|
genre = tmparr.joinToString(", ")
|
||||||
|
status = when (obj.getJSONArray("status").getJSONObject(0).getInt("tag_id")) {
|
||||||
|
2310 -> SManga.COMPLETED
|
||||||
|
2309 -> SManga.ONGOING
|
||||||
|
else -> SManga.UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
arr = obj.getJSONArray("types")
|
description = obj.getString("description")
|
||||||
tmparr.clear()
|
} else {
|
||||||
for (i in 0 until arr.length()) {
|
val data = obj.getJSONObject("data").getJSONObject("info")
|
||||||
tmparr.add(arr.getJSONObject(i).getString("tag_name"))
|
title = data.getString("title")
|
||||||
}
|
thumbnail_url = data.getString("cover")
|
||||||
genre = tmparr.joinToString(", ")
|
author = data.getString("authors")
|
||||||
status = when (obj.getJSONArray("status").getJSONObject(0).getInt("tag_id")) {
|
genre = data.getString("types").replace("/", ", ")
|
||||||
2310 -> SManga.COMPLETED
|
status = when (data.getString("status")) {
|
||||||
2309 -> SManga.ONGOING
|
"连载中" -> SManga.ONGOING
|
||||||
else -> SManga.UNKNOWN
|
"已完结" -> SManga.COMPLETED
|
||||||
|
else -> SManga.UNKNOWN
|
||||||
|
}
|
||||||
|
description = data.getString("description")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
description = obj.getString("description")
|
override fun chapterListRequest(manga: SManga): Request = throw UnsupportedOperationException("Not used.")
|
||||||
|
|
||||||
|
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
|
||||||
|
val cid = extractComicIdFromMangaUrlRegex.find(manga.url)!!.groups[1]!!.value
|
||||||
|
return if (manga.status != SManga.LICENSED) {
|
||||||
|
try {
|
||||||
|
val response = client.newCall(GET("$v3apiUrl/comic/comic_$cid.json", headers)).execute()
|
||||||
|
val sChapter = chapterListParse(response)
|
||||||
|
Observable.just(sChapter)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
val response = client.newCall(GET("$apiUrl/dynamic/comicinfo/$cid.json", headers)).execute()
|
||||||
|
val sChapter = chapterListParse(response)
|
||||||
|
Observable.just(sChapter)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Observable.error(e)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Observable.error(Exception("Licensed - No chapters to show"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
val obj = JSONObject(response.body()!!.string())
|
val obj = JSONObject(response.body()!!.string())
|
||||||
val ret = ArrayList<SChapter>()
|
val ret = ArrayList<SChapter>()
|
||||||
val cid = obj.getString("id")
|
|
||||||
val arr = obj.getJSONArray("chapters")
|
if (response.request().url().toString().startsWith(v3apiUrl)) {
|
||||||
for (i in 0 until arr.length()) {
|
val cid = obj.getString("id")
|
||||||
val obj2 = arr.getJSONObject(i)
|
val chaptersList = obj.getJSONArray("chapters")
|
||||||
val arr2 = obj2.getJSONArray("data")
|
for (i in 0 until chaptersList.length()) {
|
||||||
val prefix = obj2.getString("title")
|
val chapterObj = chaptersList.getJSONObject(i)
|
||||||
for (j in 0 until arr2.length()) {
|
val chapterData = chapterObj.getJSONArray("data")
|
||||||
val chapter = arr2.getJSONObject(j)
|
val prefix = chapterObj.getString("title")
|
||||||
|
for (j in 0 until chapterData.length()) {
|
||||||
|
val chapter = chapterData.getJSONObject(j)
|
||||||
|
ret.add(
|
||||||
|
SChapter.create().apply {
|
||||||
|
name = "$prefix: ${chapter.getString("chapter_title")}"
|
||||||
|
date_upload = chapter.getString("updatetime").toLong() * 1000 // milliseconds
|
||||||
|
url = "https://api.m.dmzj1.com/comic/chapter/$cid/${chapter.getString("chapter_id")}.html"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fallback to old api
|
||||||
|
val chaptersList = obj.getJSONObject("data").getJSONArray("list")
|
||||||
|
for (i in 0 until chaptersList.length()) {
|
||||||
|
val chapter = chaptersList.getJSONObject(i)
|
||||||
ret.add(
|
ret.add(
|
||||||
SChapter.create().apply {
|
SChapter.create().apply {
|
||||||
name = "$prefix: ${chapter.getString("chapter_title")}"
|
name = chapter.getString("chapter_name")
|
||||||
date_upload = chapter.getString("updatetime").toLong() * 1000 // milliseconds
|
date_upload = chapter.getString("updatetime").toLong() * 1000
|
||||||
url = "https://api.m.dmzj1.com/comic/chapter/$cid/${chapter.getString("chapter_id")}.html"
|
url = "$oldPageListApiUrl/${chapter.getString("comic_id")}/${chapter.getString("id")}.html"
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -229,22 +326,37 @@ class Dmzj : ConfigurableSource, HttpSource() {
|
||||||
override fun pageListRequest(chapter: SChapter) = GET(chapter.url, headers) // Bypass base url
|
override fun pageListRequest(chapter: SChapter) = GET(chapter.url, headers) // Bypass base url
|
||||||
|
|
||||||
override fun pageListParse(response: Response): List<Page> {
|
override fun pageListParse(response: Response): List<Page> {
|
||||||
// some chapters are hidden and won't return a JSONObject from api.m.dmzj, have to get them through v3api (but images won't be as HQ)
|
val arr = if (response.request().url().toString().startsWith(oldPageListApiUrl)) {
|
||||||
val arr = try {
|
JSONObject(response.body()!!.string()).getJSONArray("page_url")
|
||||||
val obj = JSONObject(response.body()!!.string())
|
} else {
|
||||||
obj.getJSONObject("chapter").getJSONArray("page_url") // api.m.dmzj1.com already return HD image url
|
// some chapters are hidden and won't return a JSONObject from api.m.dmzj, have to get them through v3api (but images won't be as HQ)
|
||||||
} catch (_: Exception) {
|
try {
|
||||||
// example url: http://v3api.dmzj.com/chapter/44253/101852.json
|
val obj = JSONObject(response.body()!!.string())
|
||||||
val url = response.request().url().toString()
|
obj.getJSONObject("chapter").getJSONArray("page_url") // api.m.dmzj1.com already return HD image url
|
||||||
.replace("api.m", "v3api")
|
} catch (_: Exception) {
|
||||||
.replace("comic/", "")
|
// example url: http://v3api.dmzj.com/chapter/44253/101852.json
|
||||||
.replace(".html", ".json")
|
val url = response.request().url().toString()
|
||||||
val obj = client.newCall(GET(url, headers)).execute().let { JSONObject(it.body()!!.string()) }
|
.replace("api.m", "v3api")
|
||||||
obj.getJSONArray("page_url_hd") // page_url in v3api.dmzj1.com will return compressed image, page_url_hd will return HD image url as api.m.dmzj1.com does.
|
.replace("comic/", "")
|
||||||
|
.replace(".html", ".json")
|
||||||
|
val obj = client.newCall(GET(url, headers)).execute().let { JSONObject(it.body()!!.string()) }
|
||||||
|
obj.getJSONArray("page_url_hd") // page_url in v3api.dmzj1.com will return compressed image, page_url_hd will return HD image url as api.m.dmzj1.com does.
|
||||||
|
} catch (_: Exception) {
|
||||||
|
// Fallback to old api
|
||||||
|
// example url: https://m.dmzj.com/chapinfo/44253/101852.html
|
||||||
|
val url = response.request().url().toString()
|
||||||
|
.replaceFirst("api.", "")
|
||||||
|
.replaceFirst(".dmzj1.", ".dmzj.")
|
||||||
|
.replaceFirst("comic/chapter", "chapinfo")
|
||||||
|
val obj = client.newCall(GET(url, headers)).execute().let { JSONObject(it.body()!!.string()) }
|
||||||
|
obj.getJSONArray("page_url")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val ret = ArrayList<Page>(arr.length())
|
val ret = ArrayList<Page>(arr.length())
|
||||||
for (i in 0 until arr.length()) {
|
for (i in 0 until arr.length()) {
|
||||||
ret.add(Page(i, "", arr.getString(i).replace("http:", "https:")))
|
ret.add(
|
||||||
|
Page(i, "", arr.getString(i).replace("http:", "https:").replace("dmzj.com", "dmzj1.com"))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
@ -359,10 +471,6 @@ class Dmzj : ConfigurableSource, HttpSource() {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Headers
|
|
||||||
override fun headersBuilder() =
|
|
||||||
super.headersBuilder().add("Referer", "https://www.dmzj1.com/")!!
|
|
||||||
|
|
||||||
private open class UriPartFilter(
|
private open class UriPartFilter(
|
||||||
displayName: String,
|
displayName: String,
|
||||||
val vals: Array<Pair<String, String>>,
|
val vals: Array<Pair<String, String>>,
|
||||||
|
@ -466,6 +574,11 @@ class Dmzj : ConfigurableSource, HttpSource() {
|
||||||
private const val IMAGE_CDN_RATELIMIT_PREF_TITLE = "图片CDN每秒连接数限制" // "Ratelimit permits per second for image CDN"
|
private const val IMAGE_CDN_RATELIMIT_PREF_TITLE = "图片CDN每秒连接数限制" // "Ratelimit permits per second for image CDN"
|
||||||
private const val IMAGE_CDN_RATELIMIT_PREF_SUMMARY = "此值影响加载图片时发起连接请求的数量。调低此值可能减小图片加载错误的几率,但加载速度也会变慢。需要重启软件以生效。\n当前值:%s" // "This value affects network request amount for loading image. Lower this value may reduce the chance to get error when loading image, but loading speed will be slower too. Tachiyomi restart required. Current value: %s"
|
private const val IMAGE_CDN_RATELIMIT_PREF_SUMMARY = "此值影响加载图片时发起连接请求的数量。调低此值可能减小图片加载错误的几率,但加载速度也会变慢。需要重启软件以生效。\n当前值:%s" // "This value affects network request amount for loading image. Lower this value may reduce the chance to get error when loading image, but loading speed will be slower too. Tachiyomi restart required. Current value: %s"
|
||||||
|
|
||||||
|
private val extractComicIdFromWebpageRegex = Regex("""addSubscribe\((\d+)\)""")
|
||||||
|
private val checkComicIdIsNumericalRegex = Regex("""^\d+$""")
|
||||||
|
private val extractComicIdFromMangaUrlRegex = Regex("""(\d+)\.(json|html)""") // Get comic ID from manga.url
|
||||||
|
|
||||||
private val ENTRIES_ARRAY = (1..10).map { i -> i.toString() }.toTypedArray()
|
private val ENTRIES_ARRAY = (1..10).map { i -> i.toString() }.toTypedArray()
|
||||||
|
const val PREFIX_ID_SEARCH = "id:"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package eu.kanade.tachiyomi.extension.zh.dmzj
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.ActivityNotFoundException
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Springboard that accepts https://www.dmzj.com/info/xxx intents and redirects them to
|
||||||
|
* the main tachiyomi process. The idea is to not install the intent filter unless
|
||||||
|
* you have this extension installed, but still let the main tachiyomi app control
|
||||||
|
* things.
|
||||||
|
*/
|
||||||
|
class DmzjUrlActivity : Activity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
val pathSegments = intent?.data?.pathSegments
|
||||||
|
if (pathSegments != null && pathSegments.size > 0) {
|
||||||
|
val titleId = if (pathSegments.size > 1) {
|
||||||
|
pathSegments[1] // [m,www].dmzj.com/info/{titleId}
|
||||||
|
} else {
|
||||||
|
pathSegments[0] // manhua.dmzj.com/{titleId}
|
||||||
|
}
|
||||||
|
val mainIntent = Intent().apply {
|
||||||
|
action = "eu.kanade.tachiyomi.SEARCH"
|
||||||
|
putExtra("query", "${Dmzj.PREFIX_ID_SEARCH}$titleId")
|
||||||
|
putExtra("filter", packageName)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
startActivity(mainIntent)
|
||||||
|
} catch (e: ActivityNotFoundException) {
|
||||||
|
Log.e("DmzjUrlActivity", e.toString())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.e("DmzjUrlActivity", "Could not parse uri from intent $intent")
|
||||||
|
}
|
||||||
|
|
||||||
|
finish()
|
||||||
|
exitProcess(0)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue