Remove Koushoku (#13329)
This commit is contained in:
parent
2821450458
commit
b56fe66fce
|
@ -37,7 +37,7 @@ jobs:
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "both",
|
"type": "both",
|
||||||
"regex": ".*(mangago|mangafox|hq\\s*dragon|manga\\s*host|supermangas|superhentais|union\\s*mangas|yes\\s*mangas|manhuascan|heroscan|manhwahot|leitor\\.?net|manga\\s*livre|tsuki\\s*mangas|manga\\s*yabu|mangas\\.in|mangas\\.pw|hentaikai|toptoon\\+?|cocomanga|hitomi\\.la|copymanga|neox|1manga\\.co|mangafox\\.fun|mangahere\\.onl|manga\\s*hub|mangakakalot\\.fun|manganel(?!o)|mangaonline\\.fun|mangapanda\\.onl|mangareader\\.site|mangatoday|manga\\.town|onemanga\\.info).*",
|
"regex": ".*(mangago|mangafox|hq\\s*dragon|manga\\s*host|supermangas|superhentais|union\\s*mangas|yes\\s*mangas|manhuascan|heroscan|manhwahot|leitor\\.?net|manga\\s*livre|tsuki\\s*mangas|manga\\s*yabu|mangas\\.in|mangas\\.pw|hentaikai|toptoon\\+?|cocomanga|hitomi\\.la|copymanga|neox|1manga\\.co|mangafox\\.fun|mangahere\\.onl|manga\\s*hub|mangakakalot\\.fun|manganel(?!o)|mangaonline\\.fun|mangapanda\\.onl|mangareader\\.site|mangatoday|manga\\.town|onemanga\\.info|koushoku).*",
|
||||||
"ignoreCase": true,
|
"ignoreCase": true,
|
||||||
"message": "{match} will not be added back as it is too difficult to maintain. Read #3475 for more information"
|
"message": "{match} will not be added back as it is too difficult to maintain. Read #3475 for more information"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?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=".en.koushoku.KoushokuUrlActivity"
|
|
||||||
android:excludeFromRecents="true"
|
|
||||||
android:exported="true"
|
|
||||||
android:theme="@android:style/Theme.NoDisplay">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
|
||||||
|
|
||||||
<data
|
|
||||||
android:host="koushoku.org"
|
|
||||||
android:pathPattern="/archive/..*"
|
|
||||||
android:scheme="https" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
</application>
|
|
||||||
</manifest>
|
|
|
@ -1,12 +0,0 @@
|
||||||
apply plugin: 'com.android.application'
|
|
||||||
apply plugin: 'kotlin-android'
|
|
||||||
|
|
||||||
ext {
|
|
||||||
extName = 'Koushoku'
|
|
||||||
pkgNameSuffix = 'en.koushoku'
|
|
||||||
extClass = '.Koushoku'
|
|
||||||
extVersionCode = 15
|
|
||||||
isNsfw = true
|
|
||||||
}
|
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
|
Binary file not shown.
Before Width: | Height: | Size: 8.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 14 KiB |
Binary file not shown.
Before Width: | Height: | Size: 29 KiB |
Binary file not shown.
Before Width: | Height: | Size: 50 KiB |
Binary file not shown.
Before Width: | Height: | Size: 194 KiB |
|
@ -1,290 +0,0 @@
|
||||||
package eu.kanade.tachiyomi.extension.en.koushoku
|
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.network.GET
|
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
|
||||||
import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
|
|
||||||
import eu.kanade.tachiyomi.source.model.Filter
|
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
|
||||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
|
||||||
import okhttp3.Headers
|
|
||||||
import okhttp3.HttpUrl
|
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
|
||||||
import okhttp3.OkHttpClient
|
|
||||||
import okhttp3.Request
|
|
||||||
import okhttp3.Response
|
|
||||||
import org.jsoup.nodes.Document
|
|
||||||
import org.jsoup.nodes.Element
|
|
||||||
import rx.Observable
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Locale
|
|
||||||
import kotlin.random.Random
|
|
||||||
|
|
||||||
class Koushoku : ParsedHttpSource() {
|
|
||||||
companion object {
|
|
||||||
const val PREFIX_ID_SEARCH = "id:"
|
|
||||||
|
|
||||||
const val thumbnailSelector = "figure img"
|
|
||||||
const val magazinesSelector = ".metadata a[href^='/magazines/']"
|
|
||||||
|
|
||||||
private val PATTERN_IMAGES = "(.+/)(\\d+)(.*)".toRegex()
|
|
||||||
private val DATE_FORMAT = SimpleDateFormat("E, d MMM yyy HH:mm:ss 'UTC'", Locale.US)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val baseUrl = "https://koushoku.org"
|
|
||||||
override val name = "Koushoku"
|
|
||||||
override val lang = "en"
|
|
||||||
override val supportsLatest = true
|
|
||||||
|
|
||||||
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
|
|
||||||
.addInterceptor(KoushokuWebViewInterceptor())
|
|
||||||
// Site: 40req per 1 minute
|
|
||||||
// Here: 1req per 2 sec -> 30req per 1 minute
|
|
||||||
// (somewhat lower due to caching)
|
|
||||||
.rateLimitHost("https://koushoku.org".toHttpUrl(), 1, 2)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
override fun headersBuilder(): Headers.Builder {
|
|
||||||
val chromeStableVersion = listOf("104.0.5112.69", "103.0.5060.71", "103.0.5060.70", "103.0.5060.53", "103.0.5060.129", "102.0.5005.99", "102.0.5005.98", "102.0.5005.78", "102.0.5005.125").random()
|
|
||||||
val chromeCanaryVersion = listOf("106.0.5227.0", "106.0.5209.0", "106.0.5206.0", "106.0.5201.2", "106.0.5201.0", "106.0.5200.0", "106.0.5199.0", "106.0.5197.0", "106.0.5196.0", "105.0.5195.2", "105.0.5194.0", "105.0.5193.0", "105.0.5192.0", "105.0.5191.0", "105.0.5190.0", "105.0.5189.0", "105.0.5186.0", "105.0.5185.0", "105.0.5184.0", "105.0.5182.0", "105.0.5180.0", "105.0.5179.3", "105.0.5178.0", "105.0.5177.2", "105.0.5176.0", "105.0.5175.0", "105.0.5174.0", "105.0.5173.0", "105.0.5172.0", "105.0.5171.0").random()
|
|
||||||
val chromeVersion = if (Random.nextFloat() > 0.2) chromeStableVersion else chromeCanaryVersion
|
|
||||||
|
|
||||||
val deviceInfo = if (Random.nextFloat() > 0.2) "" else "; " + listOf("SM-S908B", "SM-S908U", "SM-A536B", "SM-A536U", "SM-S901B", "SM-S901U", "SM-A736B", "SM-G973F", "SM-A528B", "SM-G975U", "SM-G990B", "SM-G990U").random()
|
|
||||||
val androidVersion = IntRange(if (deviceInfo.isEmpty()) 9 else 11, 12).random()
|
|
||||||
|
|
||||||
return super.headersBuilder()
|
|
||||||
.set("User-Agent", "Mozilla/5.0 (Linux; Android $androidVersion$deviceInfo) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/$chromeVersion Mobile Safari/537.36")
|
|
||||||
.add("Referer", "$baseUrl/")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/?page=$page", headers)
|
|
||||||
override fun latestUpdatesSelector() = "#archives.feed .entries > .entry"
|
|
||||||
override fun latestUpdatesNextPageSelector() = "footer nav li:has(a.active) + li:not(:last-child) > a"
|
|
||||||
|
|
||||||
override fun latestUpdatesFromElement(element: Element) = SManga.create().apply {
|
|
||||||
setUrlWithoutDomain(element.selectFirst("a").attr("href"))
|
|
||||||
title = element.selectFirst("[title]").attr("title")
|
|
||||||
thumbnail_url = element.selectFirst(thumbnailSelector).absUrl("src")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun searchMangaByIdRequest(id: String) = GET("$baseUrl/archive/$id", headers)
|
|
||||||
|
|
||||||
// taken from Tsumino ext
|
|
||||||
private fun searchMangaByIdParse(response: Response, id: String): MangasPage {
|
|
||||||
val details = mangaDetailsParse(response)
|
|
||||||
details.url = "/archive/$id"
|
|
||||||
return MangasPage(listOf(details), false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// taken from Tsumino ext
|
|
||||||
override fun fetchSearchManga(
|
|
||||||
page: Int,
|
|
||||||
query: String,
|
|
||||||
filters: FilterList
|
|
||||||
): Observable<MangasPage> {
|
|
||||||
return if (query.startsWith(PREFIX_ID_SEARCH)) {
|
|
||||||
val id = query.removePrefix(PREFIX_ID_SEARCH)
|
|
||||||
client.newCall(searchMangaByIdRequest(id)).asObservableSuccess()
|
|
||||||
.map { response -> searchMangaByIdParse(response, id) }
|
|
||||||
} else {
|
|
||||||
super.fetchSearchManga(page, query, filters)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
|
||||||
val url = "$baseUrl/search".toHttpUrlOrNull()!!.newBuilder()
|
|
||||||
.addQueryParameter("page", page.toString())
|
|
||||||
|
|
||||||
val filterList = if (filters.isEmpty()) getFilterList() else filters
|
|
||||||
filterList.findInstance<SortFilter>()?.addQueryParameter(url)
|
|
||||||
url.addQueryParameter("q", buildAdvQuery(query, filterList))
|
|
||||||
return GET(url.toString(), headers)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildAdvQuery(query: String, filterList: FilterList): String {
|
|
||||||
val title = if (query.isNotBlank()) "title*:\"$query\" " else ""
|
|
||||||
val filters: List<String> = filterList.filterIsInstance<Filter.Text>().map { filter ->
|
|
||||||
if (filter.state.isBlank()) return@map ""
|
|
||||||
val included = mutableListOf<String>()
|
|
||||||
val excluded = mutableListOf<String>()
|
|
||||||
val name = if (filter.name.lowercase().contentEquals("tags")) "tag" else filter.name.lowercase()
|
|
||||||
filter.state.split(",").map(String::trim).filterNot(String::isBlank).forEach { entry ->
|
|
||||||
if (entry.startsWith("-")) {
|
|
||||||
excluded.add(entry.slice(1 until entry.length))
|
|
||||||
} else {
|
|
||||||
included.add(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buildString {
|
|
||||||
if (included.isNotEmpty()) append("$name&*:\"${included.joinToString(",")}\" ")
|
|
||||||
if (excluded.isNotEmpty()) append("-$name&*:\"${excluded.joinToString(",")}\"")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "$title${
|
|
||||||
filters.filterNot(String::isBlank).joinToString(" ", transform = String::trim)
|
|
||||||
}"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun searchMangaSelector() = latestUpdatesSelector()
|
|
||||||
override fun searchMangaNextPageSelector() = latestUpdatesNextPageSelector()
|
|
||||||
override fun searchMangaFromElement(element: Element) = latestUpdatesFromElement(element)
|
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int) = GET("$baseUrl/popular?page=$page", headers)
|
|
||||||
override fun popularMangaSelector() = latestUpdatesSelector()
|
|
||||||
override fun popularMangaNextPageSelector() = latestUpdatesNextPageSelector()
|
|
||||||
override fun popularMangaFromElement(element: Element) = latestUpdatesFromElement(element)
|
|
||||||
|
|
||||||
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
|
|
||||||
return if (!manga.initialized) {
|
|
||||||
super.fetchMangaDetails(manga)
|
|
||||||
} else {
|
|
||||||
Observable.just(manga)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun mangaDetailsParse(document: Document) = SManga.create().apply {
|
|
||||||
title = document.selectFirst(".metadata > h1").text()
|
|
||||||
|
|
||||||
// Reuse cover from browse
|
|
||||||
thumbnail_url = document.selectFirst(thumbnailSelector).absUrl("src")
|
|
||||||
.replace(Regex("/\\d+\\.webp\$"), "/288.webp")
|
|
||||||
|
|
||||||
artist = document.select(".metadata a[href^='/artists/'], .metadata a[href^='/circles/']")
|
|
||||||
.joinToString { it.text() }
|
|
||||||
author = artist
|
|
||||||
genre = document.select(".metadata .tags a, $magazinesSelector")
|
|
||||||
.ifEmpty { null }?.joinToString { it.text() }
|
|
||||||
description = getDesc(document)
|
|
||||||
status = SManga.COMPLETED
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
|
||||||
val document = response.asJsoup()
|
|
||||||
|
|
||||||
return listOf(
|
|
||||||
SChapter.create().apply {
|
|
||||||
setUrlWithoutDomain(response.request.url.encodedPath)
|
|
||||||
name = "Chapter"
|
|
||||||
|
|
||||||
val dateText = document.select("tr > td:first-child:contains(Uploaded Date) + td")
|
|
||||||
.text()
|
|
||||||
date_upload = runCatching { DATE_FORMAT.parse(dateText) }
|
|
||||||
.getOrNull()
|
|
||||||
?.time
|
|
||||||
?: 0
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun chapterFromElement(element: Element) =
|
|
||||||
throw UnsupportedOperationException("Not used")
|
|
||||||
|
|
||||||
override fun chapterListSelector() = throw UnsupportedOperationException("Not used")
|
|
||||||
|
|
||||||
override fun pageListRequest(chapter: SChapter) = GET("$baseUrl${chapter.url}/1", headers)
|
|
||||||
|
|
||||||
override fun pageListParse(response: Response): List<Page> {
|
|
||||||
val document = response.asJsoup()
|
|
||||||
|
|
||||||
val totalPages = document.selectFirst(".total")?.text()?.toInt() ?: 0
|
|
||||||
if (totalPages == 0)
|
|
||||||
throw UnsupportedOperationException("Error: Empty pages (try Webview)")
|
|
||||||
|
|
||||||
val match = PATTERN_IMAGES.find(response.request.url.toString())!!
|
|
||||||
val prefix = match.groupValues[1]
|
|
||||||
val suffix = match.groupValues[3]
|
|
||||||
|
|
||||||
return (1..totalPages).map {
|
|
||||||
Page(it, "$prefix$it$suffix")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun pageListParse(document: Document): List<Page> =
|
|
||||||
throw UnsupportedOperationException("Not used")
|
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String =
|
|
||||||
document.selectFirst(".main img, main img").absUrl("src")
|
|
||||||
|
|
||||||
override fun getFilterList() = FilterList(
|
|
||||||
SortFilter(
|
|
||||||
"Sort",
|
|
||||||
arrayOf(
|
|
||||||
Sortable("ID", "id"),
|
|
||||||
Sortable("Title", "title"),
|
|
||||||
Sortable("Created Date", "created_at"),
|
|
||||||
Sortable("Uploaded Date", "published_at"),
|
|
||||||
Sortable("Pages", "pages"),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Filter.Header("Separate tags with commas (,)"),
|
|
||||||
Filter.Header("Prepend with dash (-) to exclude"),
|
|
||||||
ArtistFilter(),
|
|
||||||
CircleFilter(),
|
|
||||||
MagazineFilter(),
|
|
||||||
ParodyFilter(),
|
|
||||||
TagFilter(),
|
|
||||||
PagesFilter()
|
|
||||||
)
|
|
||||||
|
|
||||||
// Adapted from Mangadex ext
|
|
||||||
class SortFilter(displayName: String, private val sortables: Array<Sortable>) :
|
|
||||||
Filter.Sort(
|
|
||||||
displayName,
|
|
||||||
sortables.map(Sortable::title).toTypedArray(),
|
|
||||||
Selection(2, false)
|
|
||||||
) {
|
|
||||||
fun addQueryParameter(url: HttpUrl.Builder) {
|
|
||||||
if (state != null) {
|
|
||||||
val sort = sortables[state!!.index].value
|
|
||||||
val order = when (state!!.ascending) {
|
|
||||||
true -> "asc"
|
|
||||||
false -> "desc"
|
|
||||||
}
|
|
||||||
|
|
||||||
url.addQueryParameter("sort", sort)
|
|
||||||
url.addQueryParameter("order", order)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class Sortable(val title: String, val value: String) {
|
|
||||||
override fun toString(): String = title
|
|
||||||
}
|
|
||||||
|
|
||||||
class ArtistFilter : Filter.Text("Artist")
|
|
||||||
class CircleFilter : Filter.Text("Circle")
|
|
||||||
class MagazineFilter : Filter.Text("Magazine")
|
|
||||||
class ParodyFilter : Filter.Text("Parody")
|
|
||||||
class TagFilter : Filter.Text("Tags")
|
|
||||||
class PagesFilter : Filter.Text("Pages")
|
|
||||||
|
|
||||||
// Taken from nhentai ext
|
|
||||||
private inline fun <reified T> Iterable<*>.findInstance() = find { it is T } as? T
|
|
||||||
|
|
||||||
private fun getDesc(document: Document) = buildString {
|
|
||||||
val magazines = document.select(magazinesSelector)
|
|
||||||
if (magazines.isNotEmpty()) {
|
|
||||||
append("Magazines: ")
|
|
||||||
append(magazines.joinToString { it.text() })
|
|
||||||
append("\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
val parodies = document.select(".metadata a[href^='/parodies/']")
|
|
||||||
if (parodies.isNotEmpty()) {
|
|
||||||
append("Parodies: ")
|
|
||||||
append(parodies.joinToString { it.text() })
|
|
||||||
append("\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
val pages = document.selectFirst("tr > td:first-child:contains(Pages) + td")
|
|
||||||
append("Pages: ").append(pages.text()).append("\n")
|
|
||||||
|
|
||||||
val size: Element? = document.selectFirst("tr > td:first-child:contains(Size) + td")
|
|
||||||
append("Size: ").append(size?.text() ?: "Unknown")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
package eu.kanade.tachiyomi.extension.en.koushoku
|
|
||||||
|
|
||||||
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://koushoku.org/archive/xxxxx intents and redirects them to
|
|
||||||
* the main Tachiyomi process.
|
|
||||||
*/
|
|
||||||
class KoushokuUrlActivity : Activity() {
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
val pathSegments = intent?.data?.pathSegments
|
|
||||||
if (pathSegments != null && pathSegments.size > 1) {
|
|
||||||
val id = pathSegments[1]
|
|
||||||
val mainIntent = Intent().apply {
|
|
||||||
action = "eu.kanade.tachiyomi.SEARCH"
|
|
||||||
putExtra("query", "${Koushoku.PREFIX_ID_SEARCH}$id")
|
|
||||||
putExtra("filter", packageName)
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
startActivity(mainIntent)
|
|
||||||
} catch (e: ActivityNotFoundException) {
|
|
||||||
Log.e("KoushokuUrlActivity", e.toString())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.e("KoushokuUrlActivity", "could not parse uri from intent $intent")
|
|
||||||
}
|
|
||||||
|
|
||||||
finish()
|
|
||||||
exitProcess(0)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
package eu.kanade.tachiyomi.extension.en.koushoku
|
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import android.webkit.WebView
|
|
||||||
import android.webkit.WebViewClient
|
|
||||||
import okhttp3.Interceptor
|
|
||||||
import okhttp3.Response
|
|
||||||
import org.jsoup.Jsoup
|
|
||||||
import uy.kohesive.injekt.Injekt
|
|
||||||
import uy.kohesive.injekt.api.get
|
|
||||||
import java.io.IOException
|
|
||||||
import java.util.concurrent.CountDownLatch
|
|
||||||
|
|
||||||
class KoushokuWebViewInterceptor : Interceptor {
|
|
||||||
|
|
||||||
override fun intercept(chain: Interceptor.Chain): Response {
|
|
||||||
val request = chain.request()
|
|
||||||
val response = chain.proceed(request)
|
|
||||||
|
|
||||||
if (response.headers("Content-Type").any { it.contains("text/html") }) {
|
|
||||||
val responseBody = response.peekBody(1 * 1024 * 1024).string()
|
|
||||||
if (response.code == 403) {
|
|
||||||
val document = Jsoup.parse(responseBody)
|
|
||||||
if (document.selectFirst("h1")?.text()?.contains(Regex("banned$")) == true) {
|
|
||||||
throw IOException("You have been banned. Check WebView for details.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.networkResponse != null) {
|
|
||||||
try {
|
|
||||||
proceedWithWebView(response, responseBody)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
throw IOException(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun proceedWithWebView(response: Response, responseBody: String) {
|
|
||||||
val latch = CountDownLatch(1)
|
|
||||||
val handler = Handler(Looper.getMainLooper())
|
|
||||||
|
|
||||||
handler.post {
|
|
||||||
val webView = WebView(Injekt.get<Application>())
|
|
||||||
with(webView.settings) {
|
|
||||||
loadsImagesAutomatically = false
|
|
||||||
userAgentString = response.request.header("User-Agent")
|
|
||||||
}
|
|
||||||
|
|
||||||
webView.webViewClient = object : WebViewClient() {
|
|
||||||
override fun onPageFinished(view: WebView, url: String) {
|
|
||||||
webView.stopLoading()
|
|
||||||
webView.destroy()
|
|
||||||
latch.countDown()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
webView.loadDataWithBaseURL(
|
|
||||||
response.request.url.toString(),
|
|
||||||
responseBody,
|
|
||||||
"text/html",
|
|
||||||
"utf-8",
|
|
||||||
null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
latch.await()
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue