mirror of
https://github.com/tachiyomiorg/tachiyomi-extensions-inspector.git
synced 2024-12-26 00:31:49 +01:00
Fix chpater names, closes #81
This commit is contained in:
parent
8e61632155
commit
9cde46b5da
@ -15,7 +15,7 @@ import eu.kanade.tachiyomi.source.CatalogueSource
|
|||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.source.SourceFactory
|
import eu.kanade.tachiyomi.source.SourceFactory
|
||||||
import ir.armor.tachidesk.impl.ExtensionsList.extensionTableAsDataClass
|
import ir.armor.tachidesk.impl.ExtensionsList.extensionTableAsDataClass
|
||||||
import ir.armor.tachidesk.impl.util.CachedImageResponse.getCachedImageResponse
|
import ir.armor.tachidesk.impl.util.storage.CachedImageResponse.getCachedImageResponse
|
||||||
import ir.armor.tachidesk.impl.util.PackageTools.EXTENSION_FEATURE
|
import ir.armor.tachidesk.impl.util.PackageTools.EXTENSION_FEATURE
|
||||||
import ir.armor.tachidesk.impl.util.PackageTools.LIB_VERSION_MAX
|
import ir.armor.tachidesk.impl.util.PackageTools.LIB_VERSION_MAX
|
||||||
import ir.armor.tachidesk.impl.util.PackageTools.LIB_VERSION_MIN
|
import ir.armor.tachidesk.impl.util.PackageTools.LIB_VERSION_MIN
|
||||||
|
@ -11,8 +11,8 @@ import eu.kanade.tachiyomi.network.GET
|
|||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import ir.armor.tachidesk.impl.MangaList.proxyThumbnailUrl
|
import ir.armor.tachidesk.impl.MangaList.proxyThumbnailUrl
|
||||||
import ir.armor.tachidesk.impl.Source.getSource
|
import ir.armor.tachidesk.impl.Source.getSource
|
||||||
import ir.armor.tachidesk.impl.util.CachedImageResponse.clearCachedImage
|
import ir.armor.tachidesk.impl.util.storage.CachedImageResponse.clearCachedImage
|
||||||
import ir.armor.tachidesk.impl.util.CachedImageResponse.getCachedImageResponse
|
import ir.armor.tachidesk.impl.util.storage.CachedImageResponse.getCachedImageResponse
|
||||||
import ir.armor.tachidesk.impl.util.GetHttpSource.getHttpSource
|
import ir.armor.tachidesk.impl.util.GetHttpSource.getHttpSource
|
||||||
import ir.armor.tachidesk.impl.util.await
|
import ir.armor.tachidesk.impl.util.await
|
||||||
import ir.armor.tachidesk.impl.util.awaitSingle
|
import ir.armor.tachidesk.impl.util.awaitSingle
|
||||||
|
@ -9,13 +9,13 @@ package ir.armor.tachidesk.impl
|
|||||||
|
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import ir.armor.tachidesk.impl.util.CachedImageResponse.getCachedImageResponse
|
|
||||||
import ir.armor.tachidesk.impl.util.GetHttpSource.getHttpSource
|
import ir.armor.tachidesk.impl.util.GetHttpSource.getHttpSource
|
||||||
import ir.armor.tachidesk.impl.util.awaitSingle
|
import ir.armor.tachidesk.impl.util.awaitSingle
|
||||||
|
import ir.armor.tachidesk.impl.util.storage.CachedImageResponse.getCachedImageResponse
|
||||||
|
import ir.armor.tachidesk.impl.util.storage.DiskUtil
|
||||||
import ir.armor.tachidesk.model.database.table.ChapterTable
|
import ir.armor.tachidesk.model.database.table.ChapterTable
|
||||||
import ir.armor.tachidesk.model.database.table.MangaTable
|
import ir.armor.tachidesk.model.database.table.MangaTable
|
||||||
import ir.armor.tachidesk.model.database.table.PageTable
|
import ir.armor.tachidesk.model.database.table.PageTable
|
||||||
import ir.armor.tachidesk.model.database.table.SourceTable
|
|
||||||
import ir.armor.tachidesk.server.ApplicationDirs
|
import ir.armor.tachidesk.server.ApplicationDirs
|
||||||
import org.jetbrains.exposed.sql.and
|
import org.jetbrains.exposed.sql.and
|
||||||
import org.jetbrains.exposed.sql.select
|
import org.jetbrains.exposed.sql.select
|
||||||
@ -28,7 +28,7 @@ import java.io.File
|
|||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
object Page {
|
object Page {
|
||||||
/**
|
/**
|
||||||
* A page might have a imageUrl ready from the get go, or we might need to
|
* A page might have a imageUrl ready from the get go, or we might need to
|
||||||
* go an extra step and call fetchImageUrl to get it.
|
* go an extra step and call fetchImageUrl to get it.
|
||||||
*/
|
*/
|
||||||
@ -68,33 +68,28 @@ object Page {
|
|||||||
|
|
||||||
val saveDir = getChapterDir(mangaId, chapterId)
|
val saveDir = getChapterDir(mangaId, chapterId)
|
||||||
File(saveDir).mkdirs()
|
File(saveDir).mkdirs()
|
||||||
val fileName = index.toString()
|
val fileName = String.format("%03d", index) // e.g. 001.jpeg
|
||||||
|
|
||||||
return getCachedImageResponse(saveDir, fileName) {
|
return getCachedImageResponse(saveDir, fileName) {
|
||||||
source.fetchImage(tachiPage).awaitSingle()
|
source.fetchImage(tachiPage).awaitSingle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: rewrite this to match tachiyomi
|
|
||||||
private val applicationDirs by DI.global.instance<ApplicationDirs>()
|
private val applicationDirs by DI.global.instance<ApplicationDirs>()
|
||||||
fun getChapterDir(mangaId: Int, chapterId: Int): String {
|
private fun getChapterDir(mangaId: Int, chapterId: Int): String {
|
||||||
val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.first() }
|
val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.first() }
|
||||||
val sourceId = mangaEntry[MangaTable.sourceReference]
|
val source = getHttpSource(mangaEntry[MangaTable.sourceReference])
|
||||||
val source = getHttpSource(sourceId)
|
|
||||||
val sourceEntry = transaction { SourceTable.select { SourceTable.id eq sourceId }.first() }
|
|
||||||
val chapterEntry = transaction { ChapterTable.select { ChapterTable.id eq chapterId }.first() }
|
val chapterEntry = transaction { ChapterTable.select { ChapterTable.id eq chapterId }.first() }
|
||||||
|
|
||||||
val chapterDir = when {
|
val sourceDir = source.toString()
|
||||||
|
val mangaDir = DiskUtil.buildValidFilename(mangaEntry[MangaTable.title])
|
||||||
|
val chapterDir = DiskUtil.buildValidFilename(
|
||||||
|
when {
|
||||||
chapterEntry[ChapterTable.scanlator] != null -> "${chapterEntry[ChapterTable.scanlator]}_${chapterEntry[ChapterTable.name]}"
|
chapterEntry[ChapterTable.scanlator] != null -> "${chapterEntry[ChapterTable.scanlator]}_${chapterEntry[ChapterTable.name]}"
|
||||||
else -> chapterEntry[ChapterTable.name]
|
else -> chapterEntry[ChapterTable.name]
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
val mangaTitle = mangaEntry[MangaTable.title]
|
return "${applicationDirs.mangaRoot}/$sourceDir/$mangaDir/$chapterDir"
|
||||||
val sourceName = source.toString()
|
|
||||||
|
|
||||||
val mangaDir = "${applicationDirs.mangaRoot}/$sourceName/$mangaTitle/$chapterDir"
|
|
||||||
// make sure dirs exist
|
|
||||||
File(mangaDir).mkdirs()
|
|
||||||
return mangaDir
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,99 +0,0 @@
|
|||||||
package ir.armor.tachidesk.impl.util
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) Contributors to the Suwayomi project
|
|
||||||
*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.network.POST
|
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
|
||||||
import okhttp3.FormBody
|
|
||||||
import okhttp3.OkHttpClient
|
|
||||||
import java.net.URLEncoder
|
|
||||||
|
|
||||||
// TODO: finish MangaDex support
|
|
||||||
class MangaDexHelper(private val mangaDexSource: HttpSource) {
|
|
||||||
|
|
||||||
private fun clientBuilder(): OkHttpClient = clientBuilder(0)
|
|
||||||
|
|
||||||
private fun clientBuilder(
|
|
||||||
r18Toggle: Int,
|
|
||||||
okHttpClient: OkHttpClient = mangaDexSource.network.client
|
|
||||||
): OkHttpClient = okHttpClient.newBuilder()
|
|
||||||
.addNetworkInterceptor { chain ->
|
|
||||||
val originalCookies = chain.request().header("Cookie") ?: ""
|
|
||||||
val newReq = chain
|
|
||||||
.request()
|
|
||||||
.newBuilder()
|
|
||||||
.header("Cookie", "$originalCookies; ${cookiesHeader(r18Toggle)}")
|
|
||||||
.build()
|
|
||||||
chain.proceed(newReq)
|
|
||||||
}.build()
|
|
||||||
|
|
||||||
private fun cookiesHeader(r18Toggle: Int): String {
|
|
||||||
val cookies = mutableMapOf<String, String>()
|
|
||||||
cookies["mangadex_h_toggle"] = r18Toggle.toString()
|
|
||||||
return buildCookies(cookies)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildCookies(cookies: Map<String, String>) =
|
|
||||||
cookies.entries.joinToString(separator = "; ", postfix = ";") {
|
|
||||||
"${URLEncoder.encode(it.key, "UTF-8")}=${URLEncoder.encode(it.value, "UTF-8")}"
|
|
||||||
}
|
|
||||||
|
|
||||||
// fun isLogged(): Boolean {
|
|
||||||
// val httpUrl = mangaDexSource.baseUrl.toHttpUrlOrNull()!!
|
|
||||||
// return network.cookieManager.get(httpUrl).any { it.name == REMEMBER_ME }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fun login(username: String, password: String, twoFactorCode: String = ""): Boolean {
|
|
||||||
val formBody = FormBody.Builder()
|
|
||||||
.add("login_username", username)
|
|
||||||
.add("login_password", password)
|
|
||||||
.add("no_js", "1")
|
|
||||||
.add("remember_me", "1")
|
|
||||||
|
|
||||||
twoFactorCode.let {
|
|
||||||
formBody.add("two_factor", it)
|
|
||||||
}
|
|
||||||
|
|
||||||
val response = clientBuilder().newCall(
|
|
||||||
POST(
|
|
||||||
"${mangaDexSource.baseUrl}/ajax/actions.ajax.php?function=login",
|
|
||||||
mangaDexSource.headers,
|
|
||||||
formBody.build()
|
|
||||||
)
|
|
||||||
).execute()
|
|
||||||
return response.body!!.string().isEmpty()
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// fun logout(): Boolean {
|
|
||||||
// return withContext(Dispatchers.IO) {
|
|
||||||
// // https://mangadex.org/ajax/actions.ajax.php?function=logout
|
|
||||||
// val httpUrl = baseUrl.toHttpUrlOrNull()!!
|
|
||||||
// val listOfDexCookies = network.cookieManager.get(httpUrl)
|
|
||||||
// val cookie = listOfDexCookies.find { it.name == REMEMBER_ME }
|
|
||||||
// val token = cookie?.value
|
|
||||||
// if (token.isNullOrEmpty()) {
|
|
||||||
// return@withContext true
|
|
||||||
// }
|
|
||||||
// val result = clientBuilder().newCall(
|
|
||||||
// POSTWithCookie(
|
|
||||||
// "$baseUrl/ajax/actions.ajax.php?function=logout",
|
|
||||||
// REMEMBER_ME,
|
|
||||||
// token,
|
|
||||||
// headers
|
|
||||||
// )
|
|
||||||
// ).execute()
|
|
||||||
// val resultStr = result.body!!.string()
|
|
||||||
// if (resultStr.contains("success", true)) {
|
|
||||||
// network.cookieManager.remove(httpUrl)
|
|
||||||
// return@withContext true
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// false
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
package ir.armor.tachidesk.impl.util
|
package ir.armor.tachidesk.impl.util.storage
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) Contributors to the Suwayomi project
|
* Copyright (C) Contributors to the Suwayomi project
|
@ -0,0 +1,47 @@
|
|||||||
|
package ir.armor.tachidesk.impl.util.storage
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) Contributors to the Suwayomi project
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
// adopted from: https://github.com/tachiyomiorg/tachiyomi/blob/4cefbce7c34e724b409b6ba127f3c6c5c346ad8d/app/src/main/java/eu/kanade/tachiyomi/util/storage/DiskUtil.kt
|
||||||
|
object DiskUtil {
|
||||||
|
/**
|
||||||
|
* Mutate the given filename to make it valid for a FAT filesystem,
|
||||||
|
* replacing any invalid characters with "_". This method doesn't allow hidden files (starting
|
||||||
|
* with a dot), but you can manually add it later.
|
||||||
|
*/
|
||||||
|
fun buildValidFilename(origName: String): String {
|
||||||
|
val name = origName.trim('.', ' ')
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
return "(invalid)"
|
||||||
|
}
|
||||||
|
val sb = StringBuilder(name.length)
|
||||||
|
name.forEach { c ->
|
||||||
|
if (isValidFatFilenameChar(c)) {
|
||||||
|
sb.append(c)
|
||||||
|
} else {
|
||||||
|
sb.append('_')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Even though vfat allows 255 UCS-2 chars, we might eventually write to
|
||||||
|
// ext4 through a FUSE layer, so use that limit minus 15 reserved characters.
|
||||||
|
return sb.toString().take(240)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given character is a valid filename character, false otherwise.
|
||||||
|
*/
|
||||||
|
private fun isValidFatFilenameChar(c: Char): Boolean {
|
||||||
|
if (0x00.toChar() <= c && c <= 0x1f.toChar()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return when (c) {
|
||||||
|
'"', '*', '/', ':', '<', '>', '?', '\\', '|', 0x7f.toChar() -> false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user