Replace RequestDraft with plain Url

This commit is contained in:
Koitharu
2021-01-21 08:03:48 +02:00
parent 0c0214a85e
commit d85f23b320
13 changed files with 56 additions and 82 deletions

View File

@@ -3,7 +3,7 @@ dist: trusty
android: android:
components: components:
- android-30 - android-30
- build-tools-30.0.2 - build-tools-30.0.3
- platform-tools-30.0.3 - platform-tools-30.0.5
- tools - tools
script: ./gradlew -Dorg.gradle.jvmargs=-Xmx1536m assembleDebug lintDebug script: ./gradlew -Dorg.gradle.jvmargs=-Xmx1536m assembleDebug lintDebug

View File

@@ -5,10 +5,13 @@ import android.net.Uri
import android.util.Size import android.util.Size
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
import org.koin.core.component.get import org.koin.core.component.get
import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.core.model.MangaPage import org.koitharu.kotatsu.core.model.MangaPage
import org.koitharu.kotatsu.core.network.CommonHeaders
import org.koitharu.kotatsu.utils.CacheUtils
import org.koitharu.kotatsu.utils.ext.await import org.koitharu.kotatsu.utils.ext.await
import org.koitharu.kotatsu.utils.ext.medianOrNull import org.koitharu.kotatsu.utils.ext.medianOrNull
import java.io.InputStream import java.io.InputStream
@@ -25,8 +28,8 @@ object MangaUtils : KoinComponent {
suspend fun determineMangaIsWebtoon(pages: List<MangaPage>): Boolean? { suspend fun determineMangaIsWebtoon(pages: List<MangaPage>): Boolean? {
try { try {
val page = pages.medianOrNull() ?: return null val page = pages.medianOrNull() ?: return null
val pageRequest = page.source.repository.getPageRequest(page) val url = page.source.repository.getPageUrl(page)
val uri = Uri.parse(pageRequest.url) val uri = Uri.parse(url)
val size = if (uri.scheme == "cbz") { val size = if (uri.scheme == "cbz") {
val zip = ZipFile(uri.schemeSpecificPart) val zip = ZipFile(uri.schemeSpecificPart)
val entry = zip.getEntry(uri.fragment) val entry = zip.getEntry(uri.fragment)
@@ -35,7 +38,11 @@ object MangaUtils : KoinComponent {
} }
} else { } else {
val client = get<OkHttpClient>() val client = get<OkHttpClient>()
val request = pageRequest.newBuilder() val request = Request.Builder()
.url(url)
.get()
.header(CommonHeaders.REFERER, page.referer)
.cacheControl(CacheUtils.CONTROL_DISABLED)
.build() .build()
client.newCall(request).await().use { client.newCall(request).await().use {
getBitmapSize(it.body?.byteStream()) getBitmapSize(it.body?.byteStream())

View File

@@ -1,18 +0,0 @@
package org.koitharu.kotatsu.core.model
import okhttp3.Headers
import okhttp3.Request
data class RequestDraft(
val url: String,
val headers: Headers
) {
val isValid: Boolean
get() = url.isNotEmpty()
fun newBuilder(): Request.Builder = Request.Builder()
.url(url)
.get()
.headers(headers)
}

View File

@@ -17,7 +17,7 @@ interface MangaRepository {
suspend fun getPages(chapter: MangaChapter): List<MangaPage> suspend fun getPages(chapter: MangaChapter): List<MangaPage>
suspend fun getPageRequest(page: MangaPage): RequestDraft suspend fun getPageUrl(page: MangaPage): String
suspend fun getTags(): Set<MangaTag> suspend fun getTags(): Set<MangaTag>
} }

View File

@@ -1,9 +1,10 @@
package org.koitharu.kotatsu.core.parser package org.koitharu.kotatsu.core.parser
import okhttp3.Headers
import org.koitharu.kotatsu.base.domain.MangaLoaderContext import org.koitharu.kotatsu.base.domain.MangaLoaderContext
import org.koitharu.kotatsu.core.model.* import org.koitharu.kotatsu.core.model.MangaPage
import org.koitharu.kotatsu.core.network.CommonHeaders import org.koitharu.kotatsu.core.model.MangaSource
import org.koitharu.kotatsu.core.model.MangaTag
import org.koitharu.kotatsu.core.model.SortOrder
abstract class RemoteMangaRepository( abstract class RemoteMangaRepository(
protected val loaderContext: MangaLoaderContext protected val loaderContext: MangaLoaderContext
@@ -17,12 +18,7 @@ abstract class RemoteMangaRepository(
override val sortOrders: Set<SortOrder> get() = emptySet() override val sortOrders: Set<SortOrder> get() = emptySet()
override suspend fun getPageRequest(page: MangaPage): RequestDraft { override suspend fun getPageUrl(page: MangaPage): String = page.url
return RequestDraft(
url = page.url,
headers = Headers.headersOf(CommonHeaders.REFERER, page.referer)
)
}
override suspend fun getTags(): Set<MangaTag> = emptySet() override suspend fun getTags(): Set<MangaTag> = emptySet()

View File

@@ -1,12 +1,10 @@
package org.koitharu.kotatsu.core.parser.site package org.koitharu.kotatsu.core.parser.site
import androidx.collection.arraySetOf import androidx.collection.arraySetOf
import okhttp3.Headers
import org.intellij.lang.annotations.Language import org.intellij.lang.annotations.Language
import org.koitharu.kotatsu.base.domain.MangaLoaderContext import org.koitharu.kotatsu.base.domain.MangaLoaderContext
import org.koitharu.kotatsu.core.exceptions.ParseException import org.koitharu.kotatsu.core.exceptions.ParseException
import org.koitharu.kotatsu.core.model.* import org.koitharu.kotatsu.core.model.*
import org.koitharu.kotatsu.core.network.CommonHeaders
import org.koitharu.kotatsu.core.parser.RemoteMangaRepository import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
import org.koitharu.kotatsu.core.prefs.SourceSettings import org.koitharu.kotatsu.core.prefs.SourceSettings
import org.koitharu.kotatsu.utils.ext.* import org.koitharu.kotatsu.utils.ext.*
@@ -142,12 +140,11 @@ class MangaTownRepository(loaderContext: MangaLoaderContext) :
} }
} }
override suspend fun getPageRequest(page: MangaPage): RequestDraft { override suspend fun getPageUrl(page: MangaPage): String {
val domain = conf.getDomain(DOMAIN) val domain = conf.getDomain(DOMAIN)
val ssl = conf.isUseSsl(false) val ssl = conf.isUseSsl(false)
val doc = loaderContext.httpGet(page.url).parseHtml() val doc = loaderContext.httpGet(page.url).parseHtml()
val url = doc.getElementById("image").attr("src").withDomain(domain, ssl) return doc.getElementById("image").attr("src").withDomain(domain, ssl)
return RequestDraft(url, Headers.headersOf(CommonHeaders.REFERER, page.referer))
} }
override suspend fun getTags(): Set<MangaTag> { override suspend fun getTags(): Set<MangaTag> {

View File

@@ -1,11 +1,9 @@
package org.koitharu.kotatsu.core.parser.site package org.koitharu.kotatsu.core.parser.site
import androidx.collection.arraySetOf import androidx.collection.arraySetOf
import okhttp3.Headers
import org.koitharu.kotatsu.base.domain.MangaLoaderContext import org.koitharu.kotatsu.base.domain.MangaLoaderContext
import org.koitharu.kotatsu.core.exceptions.ParseException import org.koitharu.kotatsu.core.exceptions.ParseException
import org.koitharu.kotatsu.core.model.* import org.koitharu.kotatsu.core.model.*
import org.koitharu.kotatsu.core.network.CommonHeaders
import org.koitharu.kotatsu.core.parser.RemoteMangaRepository import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
import org.koitharu.kotatsu.core.prefs.SourceSettings import org.koitharu.kotatsu.core.prefs.SourceSettings
import org.koitharu.kotatsu.utils.ext.* import org.koitharu.kotatsu.utils.ext.*
@@ -118,10 +116,9 @@ class NudeMoonRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposit
} }
} }
override suspend fun getPageRequest(page: MangaPage): RequestDraft { override suspend fun getPageUrl(page: MangaPage): String {
val doc = loaderContext.httpGet(page.url).parseHtml() val doc = loaderContext.httpGet(page.url).parseHtml()
val url = doc.body().getElementById("gallery").attr("src").inContextOf(doc) return doc.body().getElementById("gallery").attr("src").inContextOf(doc)
return RequestDraft(url, Headers.headersOf(CommonHeaders.REFERER, page.referer))
} }
override suspend fun getTags(): Set<MangaTag> { override suspend fun getTags(): Set<MangaTag> {

View File

@@ -12,8 +12,8 @@ import coil.ImageLoader
import coil.request.ImageRequest import coil.request.ImageRequest
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import okhttp3.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request
import okio.IOException import okio.IOException
import org.koin.android.ext.android.get import org.koin.android.ext.android.get
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
@@ -23,7 +23,6 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseService import org.koitharu.kotatsu.base.ui.BaseService
import org.koitharu.kotatsu.base.ui.dialog.CheckBoxAlertDialog import org.koitharu.kotatsu.base.ui.dialog.CheckBoxAlertDialog
import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.core.model.RequestDraft
import org.koitharu.kotatsu.core.network.CommonHeaders import org.koitharu.kotatsu.core.network.CommonHeaders
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.local.data.MangaZip import org.koitharu.kotatsu.local.data.MangaZip
@@ -107,12 +106,7 @@ class DownloadService : BaseService() {
output = MangaZip.findInDir(destination, data) output = MangaZip.findInDir(destination, data)
output.prepare(data) output.prepare(data)
val coverUrl = data.largeCoverUrl ?: data.coverUrl val coverUrl = data.largeCoverUrl ?: data.coverUrl
downloadPage( downloadFile(coverUrl, data.url, destination).let { file ->
RequestDraft(
coverUrl,
Headers.headersOf(CommonHeaders.REFERER, data.url)
), destination
).let { file ->
output.addCover(file, MimeTypeMap.getFileExtensionFromUrl(coverUrl)) output.addCover(file, MimeTypeMap.getFileExtensionFromUrl(coverUrl))
} }
val chapters = if (chaptersIds == null) { val chapters = if (chaptersIds == null) {
@@ -126,14 +120,14 @@ class DownloadService : BaseService() {
for ((pageIndex, page) in pages.withIndex()) { for ((pageIndex, page) in pages.withIndex()) {
failsafe@ do { failsafe@ do {
try { try {
val request = repo.getPageRequest(page) val url = repo.getPageUrl(page)
val file = val file =
cache[request.url] ?: downloadPage(request, destination) cache[url] ?: downloadFile(url, page.referer, destination)
output.addPage( output.addPage(
chapter, chapter,
file, file,
pageIndex, pageIndex,
MimeTypeMap.getFileExtensionFromUrl(request.url) MimeTypeMap.getFileExtensionFromUrl(url)
) )
} catch (e: IOException) { } catch (e: IOException) {
notification.setWaitingForNetwork() notification.setWaitingForNetwork()
@@ -195,8 +189,10 @@ class DownloadService : BaseService() {
} }
} }
private suspend fun downloadPage(requestDraft: RequestDraft, destination: File): File { private suspend fun downloadFile(url: String, referer: String, destination: File): File {
val request = requestDraft.newBuilder() val request = Request.Builder()
.url(url)
.header(CommonHeaders.REFERER, referer)
.cacheControl(CacheUtils.CONTROL_DISABLED) .cacheControl(CacheUtils.CONTROL_DISABLED)
.get() .get()
.build() .build()

View File

@@ -7,7 +7,6 @@ import android.webkit.MimeTypeMap
import androidx.collection.ArraySet import androidx.collection.ArraySet
import androidx.core.net.toFile import androidx.core.net.toFile
import androidx.core.net.toUri import androidx.core.net.toUri
import okhttp3.internal.EMPTY_HEADERS
import org.koitharu.kotatsu.core.model.* import org.koitharu.kotatsu.core.model.*
import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.local.data.CbzFilter import org.koitharu.kotatsu.local.data.CbzFilter
@@ -157,9 +156,7 @@ class LocalMangaRepository(private val context: Context) : MangaRepository {
override val sortOrders = emptySet<SortOrder>() override val sortOrders = emptySet<SortOrder>()
override suspend fun getPageRequest(page: MangaPage): RequestDraft { override suspend fun getPageUrl(page: MangaPage) = page.url
return RequestDraft(page.url, EMPTY_HEADERS)
}
override suspend fun getTags() = emptySet<MangaTag>() override suspend fun getTags() = emptySet<MangaTag>()

View File

@@ -9,6 +9,7 @@ import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
import org.koitharu.kotatsu.core.model.MangaPage import org.koitharu.kotatsu.core.model.MangaPage
import org.koitharu.kotatsu.core.network.CommonHeaders import org.koitharu.kotatsu.core.network.CommonHeaders
@@ -54,17 +55,20 @@ class PageLoader(
repository = repo repository = repo
} }
return async(Dispatchers.IO) { return async(Dispatchers.IO) {
val requestDraft = repo.getPageRequest(page) val pageUrl = repo.getPageUrl(page)
check(requestDraft.isValid) { "Cannot obtain full image url" } check(pageUrl.isNotBlank()) { "Cannot obtain full image url" }
val uri = Uri.parse(requestDraft.url) val uri = Uri.parse(pageUrl)
if (uri.scheme == "cbz") { if (uri.scheme == "cbz") {
val zip = ZipFile(uri.schemeSpecificPart) val zip = ZipFile(uri.schemeSpecificPart)
val entry = zip.getEntry(uri.fragment) val entry = zip.getEntry(uri.fragment)
zip.getInputStream(entry).use { zip.getInputStream(entry).use {
cache.put(requestDraft.url, it) cache.put(pageUrl, it)
} }
} else { } else {
val request = requestDraft.newBuilder() val request = Request.Builder()
.url(pageUrl)
.get()
.header(CommonHeaders.REFERER, page.referer)
.header(CommonHeaders.ACCEPT, "image/webp,image/png;q=0.9,image/jpeg,*/*;q=0.8") .header(CommonHeaders.ACCEPT, "image/webp,image/png;q=0.9,image/jpeg,*/*;q=0.8")
.cacheControl(CacheUtils.CONTROL_DISABLED) .cacheControl(CacheUtils.CONTROL_DISABLED)
.build() .build()
@@ -76,7 +80,7 @@ class PageLoader(
"Null response" "Null response"
} }
body.byteStream().use { body.byteStream().use {
cache.put(requestDraft.url, it) cache.put(pageUrl, it)
} }
} }
} }

View File

@@ -9,6 +9,7 @@ import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
import org.koin.core.component.get import org.koin.core.component.get
import org.koitharu.kotatsu.base.domain.MangaDataRepository import org.koitharu.kotatsu.base.domain.MangaDataRepository
@@ -19,6 +20,7 @@ import org.koitharu.kotatsu.core.exceptions.MangaNotFoundException
import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.core.model.MangaChapter import org.koitharu.kotatsu.core.model.MangaChapter
import org.koitharu.kotatsu.core.model.MangaPage import org.koitharu.kotatsu.core.model.MangaPage
import org.koitharu.kotatsu.core.network.CommonHeaders
import org.koitharu.kotatsu.core.os.ShortcutsRepository import org.koitharu.kotatsu.core.os.ShortcutsRepository
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.core.prefs.ReaderMode
@@ -153,14 +155,16 @@ class ReaderViewModel(
it.chapterId == state.chapterId && it.index == state.page it.chapterId == state.chapterId && it.index == state.page
}?.toMangaPage() ?: error("Page not found") }?.toMangaPage() ?: error("Page not found")
val repo = page.source.repository val repo = page.source.repository
val pageRequest = repo.getPageRequest(page) val pageUrl = repo.getPageUrl(page)
val request = pageRequest.newBuilder() val request = Request.Builder()
.url(pageUrl)
.header(CommonHeaders.REFERER, page.referer)
.get() .get()
.build() .build()
val uri = get<OkHttpClient>().newCall(request).await().use { response -> val uri = get<OkHttpClient>().newCall(request).await().use { response ->
val fileName = val fileName =
URLUtil.guessFileName( URLUtil.guessFileName(
pageRequest.url, pageUrl,
response.contentDisposition, response.contentDisposition,
response.mimeType response.mimeType
) )

View File

@@ -6,16 +6,14 @@ import coil.request.ImageRequest
import coil.size.PixelSize import coil.size.PixelSize
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
import kotlinx.coroutines.* import kotlinx.coroutines.*
import okhttp3.Headers
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.model.MangaPage import org.koitharu.kotatsu.core.model.MangaPage
import org.koitharu.kotatsu.core.model.RequestDraft
import org.koitharu.kotatsu.core.network.CommonHeaders
import org.koitharu.kotatsu.databinding.ItemPageThumbBinding import org.koitharu.kotatsu.databinding.ItemPageThumbBinding
import org.koitharu.kotatsu.local.data.PagesCache import org.koitharu.kotatsu.local.data.PagesCache
import org.koitharu.kotatsu.reader.ui.thumbnails.PageThumbnail import org.koitharu.kotatsu.reader.ui.thumbnails.PageThumbnail
import org.koitharu.kotatsu.utils.ext.IgnoreErrors import org.koitharu.kotatsu.utils.ext.IgnoreErrors
import org.koitharu.kotatsu.utils.ext.referer
fun pageThumbnailAD( fun pageThumbnailAD(
coil: ImageLoader, coil: ImageLoader,
@@ -45,18 +43,14 @@ fun pageThumbnailAD(
text = (item.number).toString() text = (item.number).toString()
} }
job = scope.launch(Dispatchers.Default + IgnoreErrors) { job = scope.launch(Dispatchers.Default + IgnoreErrors) {
val pageRequest = item.page.preview?.let { val url = item.page.preview ?: item.page.url.let {
RequestDraft(it, Headers.headersOf(CommonHeaders.REFERER, item.page.referer)) val pageUrl = item.repository.getPageUrl(item.page)
} ?: item.page.url.let { cache[pageUrl]?.toUri()?.toString() ?: pageUrl
val pageRequest = item.repository.getPageRequest(item.page)
cache[pageRequest.url]?.toUri()?.toString()?.let {
pageRequest.copy(url = it)
} ?: pageRequest
} }
val drawable = coil.execute( val drawable = coil.execute(
ImageRequest.Builder(context) ImageRequest.Builder(context)
.data(pageRequest.url) .data(url)
.headers(pageRequest.headers) .referer(item.page.referer)
.size(thumbSize) .size(thumbSize)
.allowRgb565(true) .allowRgb565(true)
.build() .build()

View File

@@ -82,7 +82,7 @@ class RemoteRepositoryTest(source: MangaSource) : KoinTest {
val pages = runBlocking { repo.getPages(details.chapters!!.random()) } val pages = runBlocking { repo.getPages(details.chapters!!.random()) }
Assert.assertFalse(pages.isEmpty()) Assert.assertFalse(pages.isEmpty())
val page = pages.random() val page = pages.random()
val fullUrl = runBlocking { repo.getPageRequest(page) } val fullUrl = runBlocking { repo.getPageUrl(page) }
AssertX.assertContentType(fullUrl, "image/*") AssertX.assertContentType(fullUrl, "image/*")
} }