Webtoons: Add Search By Url + Deeplinking (#7026)
This commit is contained in:
parent
759b614000
commit
640b5f035d
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="eu.kanade.tachiyomi.extension">
|
||||
|
||||
<application>
|
||||
<activity
|
||||
android:name="eu.kanade.tachiyomi.multisrc.webtoons.WebtoonsUrlActivity"
|
||||
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="webtoons.com"
|
||||
android:pathPattern="/.*/.*/.*/..*"
|
||||
android:scheme="https" />
|
||||
<data
|
||||
android:host="www.webtoons.com"
|
||||
android:pathPattern="/.*/.*/.*/..*"
|
||||
android:scheme="https" />
|
||||
<data
|
||||
android:host="m.webtoons.com"
|
||||
android:pathPattern="/.*/.*/.*/..*"
|
||||
android:scheme="https" />
|
||||
<data
|
||||
android:host="webtoons.com"
|
||||
android:pathPattern="/.*/.*/.*/.*/..*"
|
||||
android:scheme="https" />
|
||||
<data
|
||||
android:host="www.webtoons.com"
|
||||
android:pathPattern="/.*/.*/.*/.*/..*"
|
||||
android:scheme="https" />
|
||||
<data
|
||||
android:host="m.webtoons.com"
|
||||
android:pathPattern="/.*/.*/.*/.*/..*"
|
||||
android:scheme="https" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
|
@ -22,6 +22,7 @@ import okhttp3.Response
|
|||
import org.json.JSONObject
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
@ -129,6 +130,35 @@ open class Webtoons(
|
|||
|
||||
override fun latestUpdatesNextPageSelector(): String? = null
|
||||
|
||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
||||
if (!query.startsWith(URL_SEARCH_PREFIX))
|
||||
return super.fetchSearchManga(page, query, filters)
|
||||
|
||||
val emptyResult = Observable.just(MangasPage(emptyList(), false))
|
||||
|
||||
// given a url to either a webtoon or an episode, returns a url path to corresponding webtoon
|
||||
fun webtoonPath(u: HttpUrl) = when {
|
||||
langCode == u.pathSegments[0] -> "/${u.pathSegments[0]}/${u.pathSegments[1]}/${u.pathSegments[2]}/list"
|
||||
else -> "/${u.pathSegments[0]}/${u.pathSegments[1]}/list" // dongmanmanhua doesn't include langCode
|
||||
}
|
||||
|
||||
return query.substringAfter(URL_SEARCH_PREFIX).toHttpUrlOrNull()?.let { url ->
|
||||
val title_no = url.queryParameter("title_no")
|
||||
val couldBeWebtoonOrEpisode = title_no != null && (url.pathSegments.size >= 3 && url.pathSegments.last().isNotEmpty())
|
||||
val isThisLang = "$url".startsWith("$baseUrl/$langCode")
|
||||
if (! (couldBeWebtoonOrEpisode && isThisLang))
|
||||
emptyResult
|
||||
else{
|
||||
val potentialUrl = "${webtoonPath(url)}?title_no=$title_no"
|
||||
fetchMangaDetails(SManga.create().apply { this.url = potentialUrl }).map {
|
||||
it.url = potentialUrl
|
||||
MangasPage(listOf(it), false)
|
||||
}
|
||||
}
|
||||
} ?: emptyResult
|
||||
}
|
||||
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
val url = "$baseUrl/$langCode/search?keyword=$query".toHttpUrlOrNull()?.newBuilder()!!
|
||||
val uriPart = (filters.find { it is SearchType } as? SearchType)?.toUriPart() ?: ""
|
||||
|
@ -156,6 +186,7 @@ open class Webtoons(
|
|||
val infoElement = document.select("#_asideDetail")
|
||||
|
||||
val manga = SManga.create()
|
||||
manga.title = document.selectFirst("h1.subj").text()
|
||||
manga.author = detailElement.select(".author:nth-of-type(1)").first()?.ownText()
|
||||
manga.artist = detailElement.select(".author:nth-of-type(2)").first()?.ownText() ?: manga.author
|
||||
manga.genre = detailElement.select(".genre").joinToString(", ") { it.text() }
|
||||
|
@ -241,4 +272,8 @@ open class Webtoons(
|
|||
Page(i, "", motiontoonPath + motiontoonJson.getString(key))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val URL_SEARCH_PREFIX = "url:"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ class WebtoonsGenerator : ThemeSourceGenerator {
|
|||
override val baseVersionCode: Int = 1
|
||||
|
||||
override val sources = listOf(
|
||||
MultiLang("Webtoons.com", "https://www.webtoons.com", listOf("en", "fr", "es", "id", "th", "zh"), className = "WebtoonsFactory", pkgName = "webtoons", overrideVersionCode = 27),
|
||||
MultiLang("Webtoons.com", "https://www.webtoons.com", listOf("en", "fr", "es", "id", "th", "zh"), className = "WebtoonsFactory", pkgName = "webtoons", overrideVersionCode = 28),
|
||||
SingleLang("Dongman Manhua", "https://www.dongmanmanhua.cn", "zh")
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package eu.kanade.tachiyomi.multisrc.webtoons
|
||||
|
||||
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://mangadex.com/title/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.
|
||||
*
|
||||
* Main goal was to make it easier to open manga in Tachiyomi in spite of the DDoS blocking
|
||||
* the usual search screen from working.
|
||||
*/
|
||||
class WebtoonsUrlActivity : Activity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val pathSegments = intent?.data?.pathSegments
|
||||
val title_no = intent?.data?.getQueryParameter("title_no")
|
||||
if (pathSegments != null && pathSegments.size >= 3 && title_no != null) {
|
||||
val mainIntent = Intent().apply {
|
||||
action = "eu.kanade.tachiyomi.SEARCH"
|
||||
putExtra("query", "${Webtoons.URL_SEARCH_PREFIX}${intent?.data?.toString()}")
|
||||
putExtra("filter", packageName)
|
||||
}
|
||||
|
||||
try {
|
||||
startActivity(mainIntent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Log.e("WebtoonsUrlActivity", e.toString())
|
||||
}
|
||||
} else {
|
||||
Log.e("WebtoonsUrlActivity", "could not parse uri from intent $intent")
|
||||
}
|
||||
|
||||
finish()
|
||||
exitProcess(0)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue