This commit is contained in:
Jobobby04 2020-08-24 17:25:10 -04:00
parent 166aebdf25
commit 80960d87f2
14 changed files with 43 additions and 96 deletions

View File

@ -51,7 +51,7 @@ class MangaDex(delegate: HttpSource, val context: Context) :
val lcFirstPathSegment = uri.pathSegments.firstOrNull()?.toLowerCase() ?: return null val lcFirstPathSegment = uri.pathSegments.firstOrNull()?.toLowerCase() ?: return null
return if (lcFirstPathSegment == "title" || lcFirstPathSegment == "manga") { return if (lcFirstPathSegment == "title" || lcFirstPathSegment == "manga") {
"/manga/${uri.pathSegments[1]}" "/manga/${uri.pathSegments[1]}/"
} else { } else {
null null
} }

View File

@ -5,6 +5,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import exh.util.DeferredField import exh.util.DeferredField
import exh.util.await
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
@ -28,7 +29,7 @@ class MigratingManga(
@Volatile @Volatile
private var manga: Manga? = null private var manga: Manga? = null
suspend fun manga(): Manga? { suspend fun manga(): Manga? {
if (manga == null) manga = db.getManga(mangaId).executeAsBlocking() if (manga == null) manga = db.getManga(mangaId).await()
return manga return manga
} }

View File

@ -23,7 +23,6 @@ import eu.kanade.tachiyomi.databinding.MigrationListControllerBinding
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.ui.base.controller.BaseController import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.browse.migration.MigrationMangaDialog import eu.kanade.tachiyomi.ui.browse.migration.MigrationMangaDialog
@ -39,7 +38,6 @@ import exh.util.RecyclerWindowInsetsListener
import exh.util.await import exh.util.await
import exh.util.executeOnIO import exh.util.executeOnIO
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -56,8 +54,7 @@ import uy.kohesive.injekt.injectLazy
class MigrationListController(bundle: Bundle? = null) : class MigrationListController(bundle: Bundle? = null) :
BaseController<MigrationListControllerBinding>(bundle), BaseController<MigrationListControllerBinding>(bundle),
MigrationProcessAdapter.MigrationProcessInterface, MigrationProcessAdapter.MigrationProcessInterface {
CoroutineScope {
init { init {
setHasOptionsMenu(true) setHasOptionsMenu(true)
@ -65,7 +62,7 @@ class MigrationListController(bundle: Bundle? = null) :
private var adapter: MigrationProcessAdapter? = null private var adapter: MigrationProcessAdapter? = null
override val coroutineContext: CoroutineContext = Job() + Dispatchers.Default val scope = CoroutineScope(Job() + Dispatchers.Default)
val config: MigrationProcedureConfig? = args.getParcelable(CONFIG_EXTRA) val config: MigrationProcedureConfig? = args.getParcelable(CONFIG_EXTRA)
@ -73,7 +70,7 @@ class MigrationListController(bundle: Bundle? = null) :
private val preferences: PreferencesHelper by injectLazy() private val preferences: PreferencesHelper by injectLazy()
private val sourceManager: SourceManager by injectLazy() private val sourceManager: SourceManager by injectLazy()
private val smartSearchEngine = SmartSearchEngine(coroutineContext, config?.extraSearchParams) private val smartSearchEngine = SmartSearchEngine(config?.extraSearchParams)
var migrationsJob: Job? = null var migrationsJob: Job? = null
private set private set
@ -99,7 +96,7 @@ class MigrationListController(bundle: Bundle? = null) :
val newMigratingManga = migratingManga ?: run { val newMigratingManga = migratingManga ?: run {
val new = config.mangaIds.map { val new = config.mangaIds.map {
MigratingManga(db, sourceManager, it, coroutineContext) MigratingManga(db, sourceManager, it, scope.coroutineContext)
} }
migratingManga = new.toMutableList() migratingManga = new.toMutableList()
new new
@ -115,13 +112,14 @@ class MigrationListController(bundle: Bundle? = null) :
adapter?.updateDataSet(newMigratingManga.map { it.toModal() }) adapter?.updateDataSet(newMigratingManga.map { it.toModal() })
if (migrationsJob == null) { if (migrationsJob == null) {
migrationsJob = launch { migrationsJob = scope.launch {
runMigrations(newMigratingManga) runMigrations(newMigratingManga)
} }
} }
} }
private suspend fun runMigrations(mangas: List<MigratingManga>) { private suspend fun runMigrations(mangas: List<MigratingManga>) {
if (config == null) return
val useSourceWithMost = preferences.useSourceWithMost().get() val useSourceWithMost = preferences.useSourceWithMost().get()
val useSmartSearch = preferences.smartMigration().get() val useSmartSearch = preferences.smartMigration().get()
@ -129,7 +127,6 @@ class MigrationListController(bundle: Bundle? = null) :
val value = it.toLongOrNull() ?: return val value = it.toLongOrNull() ?: return
sourceManager.get(value) as? CatalogueSource sourceManager.get(value) as? CatalogueSource
} }
if (config == null) return
for (manga in mangas) { for (manga in mangas) {
if (migrationsJob?.isCancelled == true) { if (migrationsJob?.isCancelled == true) {
break break
@ -164,40 +161,20 @@ class MigrationListController(bundle: Bundle? = null) :
sourceSemaphore.withPermit { sourceSemaphore.withPermit {
try { try {
val searchResult = if (useSmartSearch) { val searchResult = if (useSmartSearch) {
smartSearchEngine.smartSearch( smartSearchEngine.smartSearch(source, mangaObj.originalTitle)
source,
mangaObj.originalTitle
)
} else { } else {
smartSearchEngine.normalSearch( smartSearchEngine.normalSearch(source, mangaObj.originalTitle)
source,
mangaObj.originalTitle
)
} }
if (searchResult != null && if (searchResult != null && (searchResult.url == mangaObj.url && source.id == mangaObj.source)) {
!(
searchResult.url == mangaObj.url &&
source.id == mangaObj.source
)
) {
val localManga = val localManga =
smartSearchEngine.networkToLocalManga( smartSearchEngine.networkToLocalManga(
searchResult, searchResult,
source.id source.id
) )
val chapters = val chapters = source.fetchChapterList(localManga).toSingle().await(Schedulers.io())
source.fetchChapterList(localManga).toSingle()
.await(
Schedulers.io()
)
try { try {
syncChaptersWithSource( syncChaptersWithSource(db, chapters, localManga, source)
db,
chapters,
localManga,
source
)
} catch (e: Exception) { } catch (e: Exception) {
return@async null return@async null
} }
@ -214,34 +191,24 @@ class MigrationListController(bundle: Bundle? = null) :
} }
} }
} }
}.mapNotNull { it.await() }.maxBy { it.second }?.first }.mapNotNull { it.await() }.maxByOrNull { it.second }?.first
} else { } else {
validSources.forEachIndexed { index, source -> validSources.forEachIndexed { index, source ->
val searchResult = try { val searchResult = try {
val searchResult = if (useSmartSearch) { val searchResult = if (useSmartSearch) {
smartSearchEngine.smartSearch( smartSearchEngine.smartSearch(source, mangaObj.originalTitle)
source,
mangaObj.originalTitle
)
} else { } else {
smartSearchEngine.normalSearch( smartSearchEngine.normalSearch(source, mangaObj.originalTitle)
source,
mangaObj.originalTitle
)
} }
if (searchResult != null) { if (searchResult != null) {
val localManga = smartSearchEngine.networkToLocalManga( val localManga = smartSearchEngine.networkToLocalManga(searchResult, source.id)
searchResult,
source.id
)
val chapters = try { val chapters = try {
source.fetchChapterList(localManga).toSingle() source.fetchChapterList(localManga).toSingle().await(Schedulers.io()) ?: emptyList()
.await(Schedulers.io())
} catch (e: java.lang.Exception) { } catch (e: java.lang.Exception) {
Timber.e(e) Timber.e(e)
emptyList<SChapter>() emptyList()
} ?: emptyList() }
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
syncChaptersWithSource(db, chapters, localManga, source) syncChaptersWithSource(db, chapters, localManga, source)
} }
@ -253,9 +220,7 @@ class MigrationListController(bundle: Bundle? = null) :
} catch (e: Exception) { } catch (e: Exception) {
null null
} }
manga.progress.send(validSources.size to (index + 1)) manga.progress.send(validSources.size to (index + 1))
if (searchResult != null) return@async searchResult if (searchResult != null) return@async searchResult
} }
@ -269,12 +234,10 @@ class MigrationListController(bundle: Bundle? = null) :
if (result != null && result.thumbnail_url == null) { if (result != null && result.thumbnail_url == null) {
try { try {
val newManga = val newManga = sourceManager.getOrStub(result.source).fetchMangaDetails(result).toSingle().await()
sourceManager.getOrStub(result.source).fetchMangaDetails(result)
.toSingle().await()
result.copyFrom(newManga) result.copyFrom(newManga)
db.insertManga(result).executeAsBlocking() db.insertManga(result).await()
} catch (e: CancellationException) { } catch (e: CancellationException) {
// Ignore cancellations // Ignore cancellations
throw e throw e
@ -282,8 +245,7 @@ class MigrationListController(bundle: Bundle? = null) :
} }
} }
manga.migrationStatus = manga.migrationStatus = if (result == null) MigrationStatus.MANGA_NOT_FOUND else MigrationStatus.MANGA_FOUND
if (result == null) MigrationStatus.MANGA_NOT_FOUND else MigrationStatus.MANGA_FOUND
adapter?.sourceFinished() adapter?.sourceFinished()
manga.searchResult.initialize(result?.id) manga.searchResult.initialize(result?.id)
} }
@ -374,9 +336,7 @@ class MigrationListController(bundle: Bundle? = null) :
val result = CoroutineScope(migratingManga.manga.migrationJob).async { val result = CoroutineScope(migratingManga.manga.migrationJob).async {
val localManga = smartSearchEngine.networkToLocalManga(manga, source.id) val localManga = smartSearchEngine.networkToLocalManga(manga, source.id)
try { try {
val chapters = source.fetchChapterList(localManga).toSingle().await( val chapters = source.fetchChapterList(localManga).toSingle().await(Schedulers.io())
Schedulers.io()
)
syncChaptersWithSource(db, chapters, localManga, source) syncChaptersWithSource(db, chapters, localManga, source)
} catch (e: Exception) { } catch (e: Exception) {
return@async null return@async null
@ -386,12 +346,10 @@ class MigrationListController(bundle: Bundle? = null) :
if (result != null) { if (result != null) {
try { try {
val newManga = val newManga = sourceManager.getOrStub(result.source).fetchMangaDetails(result).toSingle().await()
sourceManager.getOrStub(result.source).fetchMangaDetails(result).toSingle()
.await()
result.copyFrom(newManga) result.copyFrom(newManga)
db.insertManga(result).executeAsBlocking() db.insertManga(result).await()
} catch (e: CancellationException) { } catch (e: CancellationException) {
// Ignore cancellations // Ignore cancellations
throw e throw e

View File

@ -107,7 +107,7 @@ class MigrationProcessAdapter(
if (MigrationFlags.hasChapters(flags)) { if (MigrationFlags.hasChapters(flags)) {
val prevMangaChapters = db.getChapters(prevManga).executeAsBlocking() val prevMangaChapters = db.getChapters(prevManga).executeAsBlocking()
val maxChapterRead = val maxChapterRead =
prevMangaChapters.filter { it.read }.maxBy { it.chapter_number }?.chapter_number prevMangaChapters.filter { it.read }.maxByOrNull { it.chapter_number }?.chapter_number
if (maxChapterRead != null) { if (maxChapterRead != null) {
val dbChapters = db.getChapters(manga).executeAsBlocking() val dbChapters = db.getChapters(manga).executeAsBlocking()
for (chapter in dbChapters) { for (chapter in dbChapters) {

View File

@ -181,7 +181,7 @@ class MigrationProcessHolder(
val mangaChapters = db.getChapters(manga).executeAsBlocking() val mangaChapters = db.getChapters(manga).executeAsBlocking()
manga_chapters.isVisible = true manga_chapters.isVisible = true
manga_chapters.text = mangaChapters.size.toString() manga_chapters.text = mangaChapters.size.toString()
val latestChapter = mangaChapters.maxBy { it.chapter_number }?.chapter_number ?: -1f val latestChapter = mangaChapters.maxByOrNull { it.chapter_number }?.chapter_number ?: -1f
if (latestChapter > 0f) { if (latestChapter > 0f) {
manga_last_chapter_label.text = context.getString( manga_last_chapter_label.text = context.getString(

View File

@ -73,7 +73,7 @@ class MigrationMangaPresenter(
val prevMangaChapters = db.getChapters(prevManga).executeAsBlocking() val prevMangaChapters = db.getChapters(prevManga).executeAsBlocking()
val maxChapterRead = val maxChapterRead =
prevMangaChapters.filter { it.read }.maxBy { it.chapter_number }?.chapter_number prevMangaChapters.filter { it.read }.maxByOrNull { it.chapter_number }?.chapter_number
if (maxChapterRead != null) { if (maxChapterRead != null) {
val dbChapters = db.getChapters(manga).executeAsBlocking() val dbChapters = db.getChapters(manga).executeAsBlocking()
for (chapter in dbChapters) { for (chapter in dbChapters) {

View File

@ -62,8 +62,6 @@ class SourceFilterController : SettingsController() {
sourcesByLang.keys.filterNot { it in activeLangsCodes } sourcesByLang.keys.filterNot { it in activeLangsCodes }
orderedLangs.forEach { lang -> orderedLangs.forEach { lang ->
val sources = sourcesByLang[lang].orEmpty().sortedBy { it.name }
// Create a preference group and set initial state and change listener // Create a preference group and set initial state and change listener
langPrefs.add( langPrefs.add(
Pair( Pair(

View File

@ -7,6 +7,7 @@ import android.widget.AutoCompleteTextView
import android.widget.TextView import android.widget.TextView
import androidx.core.widget.addTextChangedListener import androidx.core.widget.addTextChangedListener
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.elvishew.xlog.XLog
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup import com.google.android.material.chip.ChipGroup
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
@ -16,7 +17,6 @@ import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.widget.AutoCompleteAdapter import eu.kanade.tachiyomi.widget.AutoCompleteAdapter
import timber.log.Timber
open class AutoComplete(val filter: Filter.AutoComplete) : AbstractFlexibleItem<AutoComplete.Holder>() { open class AutoComplete(val filter: Filter.AutoComplete) : AbstractFlexibleItem<AutoComplete.Holder>() {
@ -43,8 +43,6 @@ open class AutoComplete(val filter: Filter.AutoComplete) : AbstractFlexibleItem<
) )
holder.autoComplete.threshold = 3 holder.autoComplete.threshold = 3
var text: String = ""
// select from auto complete // select from auto complete
holder.autoComplete.setOnItemClickListener { adapterView, _, chipPosition, _ -> holder.autoComplete.setOnItemClickListener { adapterView, _, chipPosition, _ ->
val name = adapterView.getItemAtPosition(chipPosition) as String val name = adapterView.getItemAtPosition(chipPosition) as String
@ -55,7 +53,7 @@ open class AutoComplete(val filter: Filter.AutoComplete) : AbstractFlexibleItem<
} }
// done keyboard button is pressed // done keyboard button is pressed
holder.autoComplete.setOnEditorActionListener { textView, actionId, keyEvent -> holder.autoComplete.setOnEditorActionListener { textView, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE && textView.text.toString() !in if (filter.excludePrefix != null && textView.text.toString().startsWith(filter.excludePrefix)) filter.skipAutoFillTags.map { filter.excludePrefix + it } else filter.skipAutoFillTags) { if (actionId == EditorInfo.IME_ACTION_DONE && textView.text.toString() !in if (filter.excludePrefix != null && textView.text.toString().startsWith(filter.excludePrefix)) filter.skipAutoFillTags.map { filter.excludePrefix + it } else filter.skipAutoFillTags) {
textView.text = null textView.text = null
addTag(textView.text.toString(), holder) addTag(textView.text.toString(), holder)
@ -69,14 +67,12 @@ open class AutoComplete(val filter: Filter.AutoComplete) : AbstractFlexibleItem<
if (it == null || it.isEmpty()) { if (it == null || it.isEmpty()) {
return@addTextChangedListener return@addTextChangedListener
} }
text = it.toString()
if (it.last() == ',') { if (it.last() == ',') {
val name = it.substring(0, it.length - 1) val name = it.substring(0, it.length - 1)
addTag(name, holder) addTag(name, holder)
holder.autoComplete.text = null holder.autoComplete.text = null
// mainTagAutoCompleteTextView.removeTextChangedListener(this)
} }
} }
@ -101,7 +97,7 @@ open class AutoComplete(val filter: Filter.AutoComplete) : AbstractFlexibleItem<
addChipToGroup(name, holder) addChipToGroup(name, holder)
filter.state += name filter.state += name
} else { } else {
Timber.d("Invalid tag: $name") XLog.d("Invalid tag: $name")
} }
} }

View File

@ -455,7 +455,7 @@ class LibraryPresenter(
mangas.forEach { manga -> mangas.forEach { manga ->
launchIO { launchIO {
/* SY --> */ val chapters = if (manga.source == EH_SOURCE_ID || manga.source == EXH_SOURCE_ID) { /* SY --> */ val chapters = if (manga.source == EH_SOURCE_ID || manga.source == EXH_SOURCE_ID) {
val chapter = db.getChapters(manga).executeAsBlocking().minBy { it.source_order } val chapter = db.getChapters(manga).executeAsBlocking().minByOrNull { it.source_order }
if (chapter != null && !chapter.read) listOf(chapter) else emptyList() if (chapter != null && !chapter.read) listOf(chapter) else emptyList()
} else /* SY <-- */ db.getChapters(manga).executeAsBlocking() } else /* SY <-- */ db.getChapters(manga).executeAsBlocking()
.filter { !it.read } .filter { !it.read }

View File

@ -54,7 +54,7 @@ class EHentaiUpdateHelper(context: Context) {
// Accept oldest chain // Accept oldest chain
val chainsWithAccepted = chainsObservable.map { chains -> val chainsWithAccepted = chainsObservable.map { chains ->
val acceptedChain = chains.minBy { it.manga.id!! }!! val acceptedChain = chains.minByOrNull { it.manga.id!! }!!
acceptedChain to chains acceptedChain to chains
} }
@ -91,7 +91,7 @@ class EHentaiUpdateHelper(context: Context) {
.fold(accepted.chapters) { curChapters, chapter -> .fold(accepted.chapters) { curChapters, chapter ->
val existing = curChapters.find { it.url == chapter.url } val existing = curChapters.find { it.url == chapter.url }
val newLastPageRead = chainsAsChapters.maxBy { it.last_page_read }?.last_page_read val newLastPageRead = chainsAsChapters.maxByOrNull { it.last_page_read }?.last_page_read
when { when {
existing != null -> { existing != null -> {

View File

@ -151,7 +151,7 @@ class EHentaiUpdateWorker : JobService(), CoroutineScope {
return@mapNotNull null return@mapNotNull null
} }
val chapter = db.getChaptersByMangaId(manga.id!!).asRxSingle().await().minBy { val chapter = db.getChaptersByMangaId(manga.id!!).asRxSingle().await().minByOrNull {
it.date_upload it.date_upload
} }

View File

@ -7,21 +7,15 @@ import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import exh.util.await import exh.util.await
import info.debatty.java.stringsimilarity.NormalizedLevenshtein import info.debatty.java.stringsimilarity.NormalizedLevenshtein
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.supervisorScope
import rx.schedulers.Schedulers import rx.schedulers.Schedulers
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
class SmartSearchEngine( class SmartSearchEngine(
parentContext: CoroutineContext,
private val extraSearchParams: String? = null private val extraSearchParams: String? = null
) : CoroutineScope { ) {
override val coroutineContext: CoroutineContext = parentContext + Job() + Dispatchers.Default
private val db: DatabaseHelper by injectLazy() private val db: DatabaseHelper by injectLazy()
private val normalizedLevenshtein = NormalizedLevenshtein() private val normalizedLevenshtein = NormalizedLevenshtein()
@ -52,7 +46,7 @@ class SmartSearchEngine(
}.flatMap { it.await() } }.flatMap { it.await() }
} }
return eligibleManga.maxBy { it.dist }?.manga return eligibleManga.maxByOrNull { it.dist }?.manga
} }
suspend fun normalSearch(source: CatalogueSource, title: String): SManga? { suspend fun normalSearch(source: CatalogueSource, title: String): SManga? {
@ -74,7 +68,7 @@ class SmartSearchEngine(
} }
} }
return eligibleManga.maxBy { it.dist }?.manga return eligibleManga.maxByOrNull { it.dist }?.manga
} }
private fun getSmartSearchQueries(cleanedTitle: String): List<String> { private fun getSmartSearchQueries(cleanedTitle: String): List<String> {

View File

@ -21,7 +21,7 @@ class SmartSearchPresenter(private val source: CatalogueSource?, private val con
val smartSearchChannel = Channel<SearchResults>() val smartSearchChannel = Channel<SearchResults>()
private val smartSearchEngine = SmartSearchEngine(scope.coroutineContext) private val smartSearchEngine = SmartSearchEngine()
override fun onCreate(savedState: Bundle?) { override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState) super.onCreate(savedState)

View File

@ -3,7 +3,7 @@ package exh.util
import com.elvishew.xlog.XLog import com.elvishew.xlog.XLog
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Response import okhttp3.Response
import okhttp3.ResponseBody import okhttp3.ResponseBody.Companion.toResponseBody
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
fun Response.interceptAsHtml(block: (Document) -> Unit): Response { fun Response.interceptAsHtml(block: (Document) -> Unit): Response {
@ -13,7 +13,7 @@ fun Response.interceptAsHtml(block: (Document) -> Unit): Response {
) { ) {
val bodyString = body.string() val bodyString = body.string()
val rebuiltResponse = newBuilder() val rebuiltResponse = newBuilder()
.body(ResponseBody.create(body.contentType(), bodyString)) .body(bodyString.toResponseBody(body.contentType()))
.build() .build()
try { try {
// Search for captcha // Search for captcha