mirror of
https://github.com/mihonapp/mihon.git
synced 2025-11-20 16:01:14 +01:00
Migrate to new URL import system
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
package eu.kanade.tachiyomi.source.online
|
||||
|
||||
import android.net.Uri
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import java.net.URI
|
||||
import java.net.URISyntaxException
|
||||
|
||||
interface UrlImportableSource : Source {
|
||||
val matchingHosts: List<String>
|
||||
|
||||
fun matchesUri(uri: Uri): Boolean {
|
||||
return (uri.host ?: "").toLowerCase() in matchingHosts
|
||||
}
|
||||
|
||||
// This method is allowed to block for IO if necessary
|
||||
fun mapUrlToMangaUrl(uri: Uri): String?
|
||||
|
||||
fun cleanMangaUrl(url: String): String {
|
||||
return try {
|
||||
val uri = URI(url)
|
||||
var out = uri.path
|
||||
if (uri.query != null)
|
||||
out += "?" + uri.query
|
||||
if (uri.fragment != null)
|
||||
out += "#" + uri.fragment
|
||||
out
|
||||
} catch (e: URISyntaxException) {
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,10 @@ package eu.kanade.tachiyomi.source.online.all
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.elvishew.xlog.XLog
|
||||
import com.github.salomonbrys.kotson.*
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParser
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||
@@ -12,6 +16,7 @@ import eu.kanade.tachiyomi.network.asObservableWithAsyncStacktrace
|
||||
import eu.kanade.tachiyomi.source.model.*
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.source.online.LewdSource
|
||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import exh.eh.EHentaiUpdateHelper
|
||||
import exh.metadata.EX_DATE_FORMAT
|
||||
@@ -46,7 +51,7 @@ import java.lang.RuntimeException
|
||||
// TODO Consider gallery updating when doing tabbed browsing
|
||||
class EHentai(override val id: Long,
|
||||
val exh: Boolean,
|
||||
val context: Context) : HttpSource(), LewdSource<EHentaiSearchMetadata, Document> {
|
||||
val context: Context) : HttpSource(), LewdSource<EHentaiSearchMetadata, Document>, UrlImportableSource {
|
||||
override val metaClass = EHentaiSearchMetadata::class
|
||||
|
||||
val schema: String
|
||||
@@ -636,11 +641,67 @@ class EHentai(override val id: Long,
|
||||
|
||||
class GalleryNotFoundException(cause: Throwable): RuntimeException("Gallery not found!", cause)
|
||||
|
||||
// === URL IMPORT STUFF
|
||||
|
||||
override val matchingHosts: List<String> = if(exh) listOf(
|
||||
"exhentai.org"
|
||||
) else listOf(
|
||||
"g.e-hentai.org",
|
||||
"e-hentai.org"
|
||||
)
|
||||
|
||||
override fun mapUrlToMangaUrl(uri: Uri): String? {
|
||||
return when (uri.pathSegments.firstOrNull()) {
|
||||
"g" -> {
|
||||
//Is already gallery page, do nothing
|
||||
uri.toString()
|
||||
}
|
||||
"s" -> {
|
||||
//Is page, fetch gallery token and use that
|
||||
getGalleryUrlFromPage(uri)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
override fun cleanMangaUrl(url: String): String {
|
||||
return EHentaiSearchMetadata.normalizeUrl(super.cleanMangaUrl(url))
|
||||
}
|
||||
|
||||
private fun getGalleryUrlFromPage(uri: Uri): String {
|
||||
val lastSplit = uri.pathSegments.last().split("-")
|
||||
val pageNum = lastSplit.last()
|
||||
val gallery = lastSplit.first()
|
||||
val pageToken = uri.pathSegments.elementAt(1)
|
||||
|
||||
val json = JsonObject()
|
||||
json["method"] = "gtoken"
|
||||
json["pagelist"] = JsonArray().apply {
|
||||
add(JsonArray().apply {
|
||||
add(gallery.toInt())
|
||||
add(pageToken)
|
||||
add(pageNum.toInt())
|
||||
})
|
||||
}
|
||||
|
||||
val outJson = JsonParser().parse(client.newCall(Request.Builder()
|
||||
.url(EH_API_BASE)
|
||||
.post(RequestBody.create(JSON, json.toString()))
|
||||
.build()).execute().body()!!.string()).obj
|
||||
|
||||
val obj = outJson["tokenlist"].array.first()
|
||||
return "${uri.scheme}://${uri.host}/g/${obj["gid"].int}/${obj["token"].string}/"
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
private const val QUERY_PREFIX = "?f_apply=Apply+Filter"
|
||||
private const val TR_SUFFIX = "TR"
|
||||
private const val REVERSE_PARAM = "TEH_REVERSE"
|
||||
|
||||
private const val EH_API_BASE = "https://api.e-hentai.org/api.php"
|
||||
private val JSON = MediaType.parse("application/json; charset=utf-8")!!
|
||||
|
||||
private val FAVORITES_BORDER_HEX_COLORS = listOf(
|
||||
"000",
|
||||
"f00",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package eu.kanade.tachiyomi.source.online.all
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import com.github.salomonbrys.kotson.array
|
||||
import com.github.salomonbrys.kotson.get
|
||||
@@ -12,7 +13,9 @@ import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.source.model.*
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.source.online.LewdSource
|
||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import exh.GalleryAddEvent
|
||||
import exh.HITOMI_SOURCE_ID
|
||||
import exh.hitomi.HitomiNozomi
|
||||
import exh.metadata.metadata.HitomiSearchMetadata
|
||||
@@ -36,7 +39,7 @@ import java.util.*
|
||||
/**
|
||||
* Man, I hate this source :(
|
||||
*/
|
||||
class Hitomi : HttpSource(), LewdSource<HitomiSearchMetadata, Document> {
|
||||
class Hitomi : HttpSource(), LewdSource<HitomiSearchMetadata, Document>, UrlImportableSource {
|
||||
private val prefs: PreferencesHelper by injectLazy()
|
||||
private val jsonParser by lazy { JsonParser() }
|
||||
|
||||
@@ -390,6 +393,19 @@ class Hitomi : HttpSource(), LewdSource<HitomiSearchMetadata, Document> {
|
||||
.build()
|
||||
}
|
||||
|
||||
override val matchingHosts = listOf(
|
||||
"hitomi.la"
|
||||
)
|
||||
|
||||
override fun mapUrlToMangaUrl(uri: Uri): String? {
|
||||
val lcFirstPathSegment = uri.pathSegments.firstOrNull()?.toLowerCase() ?: return null
|
||||
|
||||
if(lcFirstPathSegment != "galleries" && lcFirstPathSegment != "reader")
|
||||
return null
|
||||
|
||||
return "https://hitomi.la/galleries/${uri.pathSegments[1].substringBefore('.')}.html"
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val INDEX_VERSION_CACHE_TIME_MS = 1000 * 60 * 10
|
||||
private val PAGE_SIZE = 25
|
||||
|
||||
@@ -13,7 +13,9 @@ import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.source.model.*
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.source.online.LewdSource
|
||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import exh.GalleryAddEvent
|
||||
import exh.NHENTAI_SOURCE_ID
|
||||
import exh.metadata.metadata.NHentaiSearchMetadata
|
||||
import exh.metadata.metadata.NHentaiSearchMetadata.Companion.TAG_TYPE_DEFAULT
|
||||
@@ -27,7 +29,7 @@ import rx.Observable
|
||||
* NHentai source
|
||||
*/
|
||||
|
||||
class NHentai(context: Context) : HttpSource(), LewdSource<NHentaiSearchMetadata, Response> {
|
||||
class NHentai(context: Context) : HttpSource(), LewdSource<NHentaiSearchMetadata, Response>, UrlImportableSource {
|
||||
override val metaClass = NHentaiSearchMetadata::class
|
||||
|
||||
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
|
||||
@@ -127,9 +129,6 @@ class NHentai(context: Context) : HttpSource(), LewdSource<NHentaiSearchMetadata
|
||||
override fun mangaDetailsRequest(manga: SManga)
|
||||
= nhGet(baseUrl + manga.url)
|
||||
|
||||
fun urlToDetailsRequest(url: String)
|
||||
= nhGet(baseUrl + "/api/gallery/" + url.split("/").last { it.isNotBlank() })
|
||||
|
||||
fun parseResultPage(response: Response): MangasPage {
|
||||
val doc = response.asJsoup()
|
||||
|
||||
@@ -250,7 +249,7 @@ class NHentai(context: Context) : HttpSource(), LewdSource<NHentaiSearchMetadata
|
||||
)
|
||||
|
||||
val appName by lazy {
|
||||
context.getString(R.string.app_name)!!
|
||||
context.getString(R.string.app_name)
|
||||
}
|
||||
fun nhGet(url: String, tag: Any? = null) = GET(url)
|
||||
.newBuilder()
|
||||
@@ -260,7 +259,7 @@ class NHentai(context: Context) : HttpSource(), LewdSource<NHentaiSearchMetadata
|
||||
"Chrome/56.0.2924.87 " +
|
||||
"Safari/537.36 " +
|
||||
"$appName/${BuildConfig.VERSION_CODE}")
|
||||
.tag(tag).build()!!
|
||||
.tag(tag).build()
|
||||
|
||||
override val id = NHENTAI_SOURCE_ID
|
||||
|
||||
@@ -272,6 +271,19 @@ class NHentai(context: Context) : HttpSource(), LewdSource<NHentaiSearchMetadata
|
||||
|
||||
override val supportsLatest = true
|
||||
|
||||
// === URL IMPORT STUFF
|
||||
|
||||
override val matchingHosts = listOf(
|
||||
"nhentai.net"
|
||||
)
|
||||
|
||||
override fun mapUrlToMangaUrl(uri: Uri): String? {
|
||||
if(uri.pathSegments.firstOrNull()?.toLowerCase() != "g")
|
||||
return null
|
||||
|
||||
return "https://nhentai.net/g/${uri.pathSegments[1]}/"
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val GALLERY_JSON_REGEX = Regex("new N.gallery\\((.*)\\);")
|
||||
private const val REVERSE_PARAM = "TEH_REVERSE"
|
||||
@@ -282,9 +294,4 @@ class NHentai(context: Context) : HttpSource(), LewdSource<NHentaiSearchMetadata
|
||||
JsonParser()
|
||||
}
|
||||
}
|
||||
|
||||
fun JsonElement.notNull() =
|
||||
if(this is JsonNull)
|
||||
null
|
||||
else this
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.source.model.*
|
||||
import eu.kanade.tachiyomi.source.online.LewdSource
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||
import eu.kanade.tachiyomi.util.ChapterRecognition
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import exh.metadata.metadata.PervEdenLang
|
||||
@@ -27,7 +28,7 @@ import java.util.*
|
||||
|
||||
// TODO Transform into delegated source
|
||||
class PervEden(override val id: Long, val pvLang: PervEdenLang) : ParsedHttpSource(),
|
||||
LewdSource<PervEdenSearchMetadata, Document> {
|
||||
LewdSource<PervEdenSearchMetadata, Document>, UrlImportableSource {
|
||||
/**
|
||||
* The class of the metadata used by this source
|
||||
*/
|
||||
@@ -306,6 +307,23 @@ class PervEden(override val id: Long, val pvLang: PervEdenLang) : ParsedHttpSour
|
||||
}
|
||||
}
|
||||
|
||||
override val matchingHosts = listOf("www.perveden.com")
|
||||
|
||||
override fun matchesUri(uri: Uri): Boolean {
|
||||
return super.matchesUri(uri) && uri.pathSegments.firstOrNull()?.toLowerCase() == when(pvLang) {
|
||||
PervEdenLang.en -> "en-manga"
|
||||
PervEdenLang.it -> "it-manga"
|
||||
}
|
||||
}
|
||||
|
||||
override fun mapUrlToMangaUrl(uri: Uri): String? {
|
||||
val newUri = Uri.parse("http://www.perveden.com/").buildUpon()
|
||||
uri.pathSegments.take(3).forEach {
|
||||
newUri.appendPath(it)
|
||||
}
|
||||
return newUri.toString()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val DATE_FORMAT = SimpleDateFormat("MMM d, yyyy", Locale.US).apply {
|
||||
timeZone = TimeZone.getTimeZone("GMT")
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package eu.kanade.tachiyomi.source.online.english
|
||||
|
||||
import android.net.Uri
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.source.online.LewdSource
|
||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import exh.metadata.metadata.HentaiCafeSearchMetadata
|
||||
import exh.metadata.metadata.HentaiCafeSearchMetadata.Companion.TAG_TYPE_DEFAULT
|
||||
@@ -18,7 +20,7 @@ import org.jsoup.nodes.Document
|
||||
import rx.Observable
|
||||
|
||||
class HentaiCafe(delegate: HttpSource) : DelegatedHttpSource(delegate),
|
||||
LewdSource<HentaiCafeSearchMetadata, Document> {
|
||||
LewdSource<HentaiCafeSearchMetadata, Document>, UrlImportableSource {
|
||||
/**
|
||||
* An ISO 639-1 compliant language code (two letters in lower case).
|
||||
*/
|
||||
@@ -88,4 +90,17 @@ class HentaiCafe(delegate: HttpSource) : DelegatedHttpSource(delegate),
|
||||
}
|
||||
)
|
||||
}.toObservable()
|
||||
|
||||
override val matchingHosts = listOf(
|
||||
"hentai.cafe"
|
||||
)
|
||||
|
||||
override fun mapUrlToMangaUrl(uri: Uri): String? {
|
||||
val lcFirstPathSegment = uri.pathSegments.firstOrNull()?.toLowerCase() ?: return null
|
||||
|
||||
return if(lcFirstPathSegment == "manga")
|
||||
"https://hentai.cafe/${uri.pathSegments[2]}"
|
||||
else
|
||||
"https://hentai.cafe/$lcFirstPathSegment"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,10 @@ import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.source.model.*
|
||||
import eu.kanade.tachiyomi.source.online.LewdSource
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import eu.kanade.tachiyomi.util.toast
|
||||
import exh.GalleryAddEvent
|
||||
import exh.TSUMINO_SOURCE_ID
|
||||
import exh.ui.captcha.ActionCompletionVerifier
|
||||
import exh.ui.captcha.BrowserActionActivity
|
||||
@@ -33,7 +35,10 @@ import uy.kohesive.injekt.injectLazy
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class Tsumino(private val context: Context): ParsedHttpSource(), LewdSource<TsuminoSearchMetadata, Document>, ActionCompletionVerifier {
|
||||
class Tsumino(private val context: Context): ParsedHttpSource(),
|
||||
LewdSource<TsuminoSearchMetadata, Document>,
|
||||
ActionCompletionVerifier,
|
||||
UrlImportableSource {
|
||||
override val metaClass = TsuminoSearchMetadata::class
|
||||
|
||||
private val preferences: PreferencesHelper by injectLazy()
|
||||
@@ -400,6 +405,19 @@ class Tsumino(private val context: Context): ParsedHttpSource(), LewdSource<Tsum
|
||||
class MinimumRatingFilter : Filter.Select<String>("Minimum rating", (0 .. 5).map { "$it stars" }.toTypedArray())
|
||||
class ExcludeParodiesFilter : Filter.CheckBox("Exclude parodies")
|
||||
|
||||
override val matchingHosts = listOf(
|
||||
"www.tsumino.com"
|
||||
)
|
||||
|
||||
override fun mapUrlToMangaUrl(uri: Uri): String? {
|
||||
val lcFirstPathSegment = uri.pathSegments.firstOrNull()?.toLowerCase() ?: return null
|
||||
|
||||
if(lcFirstPathSegment != "read" && lcFirstPathSegment != "book")
|
||||
return null
|
||||
|
||||
return "https://tsumino.com/Book/Info/${uri.pathSegments[2]}"
|
||||
}
|
||||
|
||||
companion object {
|
||||
val jsonParser by lazy {
|
||||
JsonParser()
|
||||
|
||||
Reference in New Issue
Block a user