mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-07-10 14:24:34 -05:00
[skip ci] Formatting
This commit is contained in:
@@ -23,9 +23,7 @@ interface CatalogueSource : Source {
|
||||
* @param page the page number to retrieve.
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
suspend fun getPopularManga(page: Int): MangasPage {
|
||||
return fetchPopularManga(page).awaitSingle()
|
||||
}
|
||||
suspend fun getPopularManga(page: Int): MangasPage = fetchPopularManga(page).awaitSingle()
|
||||
|
||||
/**
|
||||
* Get a page with a list of manga.
|
||||
@@ -40,9 +38,7 @@ interface CatalogueSource : Source {
|
||||
page: Int,
|
||||
query: String,
|
||||
filters: FilterList,
|
||||
): MangasPage {
|
||||
return fetchSearchManga(page, query, filters).awaitSingle()
|
||||
}
|
||||
): MangasPage = fetchSearchManga(page, query, filters).awaitSingle()
|
||||
|
||||
/**
|
||||
* Get a page with a list of latest manga updates.
|
||||
@@ -51,9 +47,7 @@ interface CatalogueSource : Source {
|
||||
* @param page the page number to retrieve.
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
suspend fun getLatestUpdates(page: Int): MangasPage {
|
||||
return fetchLatestUpdates(page).awaitSingle()
|
||||
}
|
||||
suspend fun getLatestUpdates(page: Int): MangasPage = fetchLatestUpdates(page).awaitSingle()
|
||||
|
||||
/**
|
||||
* Returns the list of filters for the source.
|
||||
|
||||
@@ -31,9 +31,7 @@ interface Source {
|
||||
* @return the updated manga.
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
suspend fun getMangaDetails(manga: SManga): SManga {
|
||||
return fetchMangaDetails(manga).awaitSingle()
|
||||
}
|
||||
suspend fun getMangaDetails(manga: SManga): SManga = fetchMangaDetails(manga).awaitSingle()
|
||||
|
||||
/**
|
||||
* Get all the available chapters for a manga.
|
||||
@@ -43,9 +41,7 @@ interface Source {
|
||||
* @return the chapters for the manga.
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
suspend fun getChapterList(manga: SManga): List<SChapter> {
|
||||
return fetchChapterList(manga).awaitSingle()
|
||||
}
|
||||
suspend fun getChapterList(manga: SManga): List<SChapter> = fetchChapterList(manga).awaitSingle()
|
||||
|
||||
/**
|
||||
* Get the list of pages a chapter has. Pages should be returned
|
||||
@@ -56,9 +52,7 @@ interface Source {
|
||||
* @return the pages for the chapter.
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
suspend fun getPageList(chapter: SChapter): List<Page> {
|
||||
return fetchPageList(chapter).awaitSingle()
|
||||
}
|
||||
suspend fun getPageList(chapter: SChapter): List<Page> = fetchPageList(chapter).awaitSingle()
|
||||
|
||||
@Deprecated(
|
||||
"Use the non-RxJava API instead",
|
||||
|
||||
@@ -59,7 +59,8 @@ import com.github.junrar.Archive as JunrarArchive
|
||||
class LocalSource(
|
||||
private val fileSystem: LocalSourceFileSystem,
|
||||
private val coverManager: LocalCoverManager,
|
||||
) : CatalogueSource, UnmeteredSource {
|
||||
) : CatalogueSource,
|
||||
UnmeteredSource {
|
||||
private val json: Json by injectLazy()
|
||||
private val xml: XML by injectLazy()
|
||||
|
||||
@@ -93,7 +94,8 @@ class LocalSource(
|
||||
// Filter out files that are hidden and is not a folder
|
||||
.filter { it.isDirectory && !it.name.startsWith('.') }
|
||||
.distinctBy { it.name }
|
||||
.filter { // Filter by query or last modified
|
||||
.filter {
|
||||
// Filter by query or last modified
|
||||
if (lastModifiedLimit == 0L) {
|
||||
it.name.contains(query, ignoreCase = true)
|
||||
} else {
|
||||
@@ -134,7 +136,8 @@ class LocalSource(
|
||||
url = mangaDir.name
|
||||
|
||||
// Try to find the cover
|
||||
coverManager.find(mangaDir.name)
|
||||
coverManager
|
||||
.find(mangaDir.name)
|
||||
?.takeIf(File::exists)
|
||||
?.let { thumbnail_url = it.absolutePath }
|
||||
}
|
||||
@@ -238,7 +241,7 @@ class LocalSource(
|
||||
for (chapter in chapterArchives) {
|
||||
when (Format.valueOf(chapter)) {
|
||||
is Format.Zip -> {
|
||||
ZipFile(chapter).use { zip: ZipFile ->
|
||||
ZipFile.builder().setFile(chapter).get().use { zip: ZipFile ->
|
||||
zip.getEntry(COMIC_INFO_FILE)?.let { comicInfoFile ->
|
||||
zip.getInputStream(comicInfoFile).buffered().use { stream ->
|
||||
return copyComicInfoFile(stream, folderPath)
|
||||
@@ -264,13 +267,12 @@ class LocalSource(
|
||||
private fun copyComicInfoFile(
|
||||
comicInfoFileStream: InputStream,
|
||||
folderPath: String?,
|
||||
): File {
|
||||
return File("$folderPath/$COMIC_INFO_FILE").apply {
|
||||
): File =
|
||||
File("$folderPath/$COMIC_INFO_FILE").apply {
|
||||
outputStream().use { outputStream ->
|
||||
comicInfoFileStream.use { it.copyTo(outputStream) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalXmlUtilApi::class)
|
||||
private fun setMangaDetailsFromComicInfoFile(
|
||||
@@ -286,8 +288,9 @@ class LocalSource(
|
||||
}
|
||||
|
||||
// Chapters
|
||||
override suspend fun getChapterList(manga: SManga): List<SChapter> {
|
||||
return fileSystem.getFilesInMangaDirectory(manga.url)
|
||||
override suspend fun getChapterList(manga: SManga): List<SChapter> =
|
||||
fileSystem
|
||||
.getFilesInMangaDirectory(manga.url)
|
||||
// Only keep supported formats
|
||||
.filter { it.isDirectory || Archive.isSupported(it) }
|
||||
.map { chapterFile ->
|
||||
@@ -312,22 +315,21 @@ class LocalSource(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.sortedWith { c1, c2 ->
|
||||
}.sortedWith { c1, c2 ->
|
||||
val c = c2.chapter_number.compareTo(c1.chapter_number)
|
||||
if (c == 0) c2.name.compareToCaseInsensitiveNaturalOrder(c1.name) else c
|
||||
}
|
||||
.toList()
|
||||
}
|
||||
}.toList()
|
||||
|
||||
// Filters
|
||||
override fun getFilterList() = FilterList(OrderBy.Popular())
|
||||
|
||||
// TODO Fix Memory Leak
|
||||
override suspend fun getPageList(chapter: SChapter): List<Page> {
|
||||
return when (val format = getFormat(chapter)) {
|
||||
override suspend fun getPageList(chapter: SChapter): List<Page> =
|
||||
when (val format = getFormat(chapter)) {
|
||||
is Format.Directory -> {
|
||||
format.file.listFiles().orEmpty()
|
||||
format.file
|
||||
.listFiles()
|
||||
.orEmpty()
|
||||
.filter { !it.isDirectory && ImageUtil.isImage(it.name, it::inputStream) }
|
||||
.sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }
|
||||
.mapIndexed { index, page ->
|
||||
@@ -359,11 +361,11 @@ class LocalSource(
|
||||
pages
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getFormat(chapter: SChapter): Format {
|
||||
try {
|
||||
return fileSystem.getBaseDirectories()
|
||||
return fileSystem
|
||||
.getBaseDirectories()
|
||||
.map { dir -> File(dir, chapter.url) }
|
||||
.find { it.exists() }
|
||||
?.let(Format.Companion::valueOf)
|
||||
@@ -378,21 +380,23 @@ class LocalSource(
|
||||
private fun updateCover(
|
||||
chapter: SChapter,
|
||||
manga: SManga,
|
||||
): File? {
|
||||
return try {
|
||||
): File? =
|
||||
try {
|
||||
when (val format = getFormat(chapter)) {
|
||||
is Format.Directory -> {
|
||||
val entry =
|
||||
format.file.listFiles()
|
||||
format.file
|
||||
.listFiles()
|
||||
?.sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }
|
||||
?.find { !it.isDirectory && ImageUtil.isImage(it.name) { FileInputStream(it) } }
|
||||
|
||||
entry?.let { coverManager.update(manga, it.inputStream()) }
|
||||
}
|
||||
is Format.Zip -> {
|
||||
ZipFile(format.file).use { zip ->
|
||||
ZipFile.builder().setFile(format.file).get().use { zip ->
|
||||
val entry =
|
||||
zip.entries.toList()
|
||||
zip.entries
|
||||
.toList()
|
||||
.sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }
|
||||
.find { !it.isDirectory && ImageUtil.isImage(it.name) { zip.getInputStream(it) } }
|
||||
|
||||
@@ -412,7 +416,8 @@ class LocalSource(
|
||||
is Format.Epub -> {
|
||||
EpubFile(format.file).use { epub ->
|
||||
val entry =
|
||||
epub.getImagesFromPages()
|
||||
epub
|
||||
.getImagesFromPages()
|
||||
.firstOrNull()
|
||||
?.let { epub.getEntry(it) }
|
||||
|
||||
@@ -424,7 +429,6 @@ class LocalSource(
|
||||
logger.error(e) { "Error updating cover for ${manga.title}" }
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ID = 0L
|
||||
|
||||
@@ -2,12 +2,14 @@ package eu.kanade.tachiyomi.source.local.filter
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.Filter
|
||||
|
||||
sealed class OrderBy(selection: Selection) : Filter.Sort(
|
||||
"Order by",
|
||||
arrayOf("Title", "Date"),
|
||||
selection,
|
||||
) {
|
||||
class Popular() : OrderBy(Selection(0, true))
|
||||
sealed class OrderBy(
|
||||
selection: Selection,
|
||||
) : Filter.Sort(
|
||||
"Order by",
|
||||
arrayOf("Title", "Date"),
|
||||
selection,
|
||||
) {
|
||||
class Popular : OrderBy(Selection(0, true))
|
||||
|
||||
class Latest() : OrderBy(Selection(1, false))
|
||||
class Latest : OrderBy(Selection(1, false))
|
||||
}
|
||||
|
||||
@@ -11,15 +11,15 @@ private const val DEFAULT_COVER_NAME = "cover.jpg"
|
||||
class LocalCoverManager(
|
||||
private val fileSystem: LocalSourceFileSystem,
|
||||
) {
|
||||
fun find(mangaUrl: String): File? {
|
||||
return fileSystem.getFilesInMangaDirectory(mangaUrl)
|
||||
fun find(mangaUrl: String): File? =
|
||||
fileSystem
|
||||
.getFilesInMangaDirectory(mangaUrl)
|
||||
// Get all file whose names start with 'cover'
|
||||
.filter { it.isFile && it.nameWithoutExtension.equals("cover", ignoreCase = true) }
|
||||
// Get the first actual image
|
||||
.firstOrNull {
|
||||
ImageUtil.isImage(it.name) { it.inputStream() }
|
||||
}
|
||||
}
|
||||
|
||||
fun update(
|
||||
manga: SManga,
|
||||
|
||||
@@ -3,13 +3,21 @@ package eu.kanade.tachiyomi.source.local.io
|
||||
import java.io.File
|
||||
|
||||
sealed interface Format {
|
||||
data class Directory(val file: File) : Format
|
||||
data class Directory(
|
||||
val file: File,
|
||||
) : Format
|
||||
|
||||
data class Zip(val file: File) : Format
|
||||
data class Zip(
|
||||
val file: File,
|
||||
) : Format
|
||||
|
||||
data class Rar(val file: File) : Format
|
||||
data class Rar(
|
||||
val file: File,
|
||||
) : Format
|
||||
|
||||
data class Epub(val file: File) : Format
|
||||
data class Epub(
|
||||
val file: File,
|
||||
) : Format
|
||||
|
||||
class UnknownFormatException : Exception()
|
||||
|
||||
|
||||
@@ -6,27 +6,22 @@ import java.io.File
|
||||
class LocalSourceFileSystem(
|
||||
private val applicationDirs: ApplicationDirs,
|
||||
) {
|
||||
fun getBaseDirectories(): Sequence<File> {
|
||||
return sequenceOf(File(applicationDirs.localMangaRoot))
|
||||
}
|
||||
fun getBaseDirectories(): Sequence<File> = sequenceOf(File(applicationDirs.localMangaRoot))
|
||||
|
||||
fun getFilesInBaseDirectories(): Sequence<File> {
|
||||
return getBaseDirectories()
|
||||
fun getFilesInBaseDirectories(): Sequence<File> =
|
||||
getBaseDirectories()
|
||||
// Get all the files inside all baseDir
|
||||
.flatMap { it.listFiles().orEmpty().toList() }
|
||||
}
|
||||
|
||||
fun getMangaDirectory(name: String): File? {
|
||||
return getFilesInBaseDirectories()
|
||||
fun getMangaDirectory(name: String): File? =
|
||||
getFilesInBaseDirectories()
|
||||
// Get the first mangaDir or null
|
||||
.firstOrNull { it.isDirectory && it.name == name }
|
||||
}
|
||||
|
||||
fun getFilesInMangaDirectory(name: String): Sequence<File> {
|
||||
return getFilesInBaseDirectories()
|
||||
fun getFilesInMangaDirectory(name: String): Sequence<File> =
|
||||
getFilesInBaseDirectories()
|
||||
// Filter out ones that are not related to the manga and is not a directory
|
||||
.filter { it.isDirectory && it.name == name }
|
||||
// Get all the files inside the filtered folders
|
||||
.flatMap { it.listFiles().orEmpty().toList() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,18 +6,20 @@ import java.io.File
|
||||
/**
|
||||
* Loader used to load a chapter from a .epub file.
|
||||
*/
|
||||
class EpubPageLoader(file: File) : PageLoader {
|
||||
class EpubPageLoader(
|
||||
file: File,
|
||||
) : PageLoader {
|
||||
private val epub = EpubFile(file)
|
||||
|
||||
override suspend fun getPages(): List<ReaderPage> {
|
||||
return epub.getImagesFromPages()
|
||||
override suspend fun getPages(): List<ReaderPage> =
|
||||
epub
|
||||
.getImagesFromPages()
|
||||
.mapIndexed { i, path ->
|
||||
val streamFn = { epub.getInputStream(epub.getEntry(path)!!) }
|
||||
ReaderPage(i).apply {
|
||||
stream = streamFn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun recycle() {
|
||||
epub.close()
|
||||
|
||||
@@ -12,20 +12,21 @@ import java.io.PipedOutputStream
|
||||
/**
|
||||
* Loader used to load a chapter from a .rar or .cbr file.
|
||||
*/
|
||||
class RarPageLoader(file: File) : PageLoader {
|
||||
class RarPageLoader(
|
||||
file: File,
|
||||
) : PageLoader {
|
||||
private val rar = Archive(file)
|
||||
|
||||
override suspend fun getPages(): List<ReaderPage> {
|
||||
return rar.fileHeaders.asSequence()
|
||||
override suspend fun getPages(): List<ReaderPage> =
|
||||
rar.fileHeaders
|
||||
.asSequence()
|
||||
.filter { !it.isDirectory && ImageUtil.isImage(it.fileName) { rar.getInputStream(it) } }
|
||||
.sortedWith { f1, f2 -> f1.fileName.compareToCaseInsensitiveNaturalOrder(f2.fileName) }
|
||||
.mapIndexed { i, header ->
|
||||
ReaderPage(i).apply {
|
||||
stream = { getStream(rar, header) }
|
||||
}
|
||||
}
|
||||
.toList()
|
||||
}
|
||||
}.toList()
|
||||
|
||||
override fun recycle() {
|
||||
rar.close()
|
||||
|
||||
@@ -8,20 +8,21 @@ import java.io.File
|
||||
/**
|
||||
* Loader used to load a chapter from a .zip or .cbz file.
|
||||
*/
|
||||
class ZipPageLoader(file: File) : PageLoader {
|
||||
private val zip = ZipFile(file)
|
||||
class ZipPageLoader(
|
||||
file: File,
|
||||
) : PageLoader {
|
||||
private val zip = ZipFile.builder().setFile(file).get()
|
||||
|
||||
override suspend fun getPages(): List<ReaderPage> {
|
||||
return zip.entries.asSequence()
|
||||
override suspend fun getPages(): List<ReaderPage> =
|
||||
zip.entries
|
||||
.asSequence()
|
||||
.filter { !it.isDirectory && ImageUtil.isImage(it.name) { zip.getInputStream(it) } }
|
||||
.sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }
|
||||
.mapIndexed { i, entry ->
|
||||
ReaderPage(i).apply {
|
||||
stream = { zip.getInputStream(entry) }
|
||||
}
|
||||
}
|
||||
.toList()
|
||||
}
|
||||
}.toList()
|
||||
|
||||
override fun recycle() {
|
||||
zip.close()
|
||||
|
||||
@@ -17,8 +17,7 @@ fun SManga.copyFromComicInfo(comicInfo: ComicInfo) {
|
||||
comicInfo.genre?.value,
|
||||
comicInfo.tags?.value,
|
||||
comicInfo.categories?.value,
|
||||
)
|
||||
.distinct()
|
||||
).distinct()
|
||||
.joinToString(", ") { it.trim() }
|
||||
.takeIf { it.isNotEmpty() }
|
||||
?.let { genre = it }
|
||||
@@ -29,8 +28,7 @@ fun SManga.copyFromComicInfo(comicInfo: ComicInfo) {
|
||||
comicInfo.colorist?.value,
|
||||
comicInfo.letterer?.value,
|
||||
comicInfo.coverArtist?.value,
|
||||
)
|
||||
.flatMap { it.split(", ") }
|
||||
).flatMap { it.split(", ") }
|
||||
.distinct()
|
||||
.joinToString(", ") { it.trim() }
|
||||
.takeIf { it.isNotEmpty() }
|
||||
@@ -202,14 +200,12 @@ enum class ComicInfoPublishingStatus(
|
||||
;
|
||||
|
||||
companion object {
|
||||
fun toComicInfoValue(value: Long): String {
|
||||
return entries.firstOrNull { it.sMangaModelValue == value.toInt() }?.comicInfoValue
|
||||
fun toComicInfoValue(value: Long): String =
|
||||
entries.firstOrNull { it.sMangaModelValue == value.toInt() }?.comicInfoValue
|
||||
?: UNKNOWN.comicInfoValue
|
||||
}
|
||||
|
||||
fun toSMangaValue(value: String?): Int {
|
||||
return entries.firstOrNull { it.comicInfoValue == value }?.sMangaModelValue
|
||||
fun toSMangaValue(value: String?): Int =
|
||||
entries.firstOrNull { it.comicInfoValue == value }?.sMangaModelValue
|
||||
?: UNKNOWN.sMangaModelValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,20 +2,40 @@ package eu.kanade.tachiyomi.source.model
|
||||
|
||||
// The class is originally sealed, Tachidesk adds new subclasses for serialization
|
||||
// sealed class Filter<T>(val name: String, var state: T) {
|
||||
open class Filter<T>(val name: String, var state: T) {
|
||||
open class Header(name: String) : Filter<Any>(name, 0)
|
||||
open class Filter<T>(
|
||||
val name: String,
|
||||
var state: T,
|
||||
) {
|
||||
open class Header(
|
||||
name: String,
|
||||
) : Filter<Any>(name, 0)
|
||||
|
||||
open class Separator(name: String = "") : Filter<Any>(name, 0)
|
||||
open class Separator(
|
||||
name: String = "",
|
||||
) : Filter<Any>(name, 0)
|
||||
|
||||
abstract class Select<V>(name: String, val values: Array<V>, state: Int = 0) : Filter<Int>(name, state) {
|
||||
abstract class Select<V>(
|
||||
name: String,
|
||||
val values: Array<V>,
|
||||
state: Int = 0,
|
||||
) : Filter<Int>(name, state) {
|
||||
val displayValues get() = values.map { it.toString() }
|
||||
}
|
||||
|
||||
abstract class Text(name: String, state: String = "") : Filter<String>(name, state)
|
||||
abstract class Text(
|
||||
name: String,
|
||||
state: String = "",
|
||||
) : Filter<String>(name, state)
|
||||
|
||||
abstract class CheckBox(name: String, state: Boolean = false) : Filter<Boolean>(name, state)
|
||||
abstract class CheckBox(
|
||||
name: String,
|
||||
state: Boolean = false,
|
||||
) : Filter<Boolean>(name, state)
|
||||
|
||||
abstract class TriState(name: String, state: Int = STATE_IGNORE) : Filter<Int>(name, state) {
|
||||
abstract class TriState(
|
||||
name: String,
|
||||
state: Int = STATE_IGNORE,
|
||||
) : Filter<Int>(name, state) {
|
||||
fun isIgnored() = state == STATE_IGNORE
|
||||
|
||||
fun isIncluded() = state == STATE_INCLUDE
|
||||
@@ -29,11 +49,20 @@ open class Filter<T>(val name: String, var state: T) {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Group<V>(name: String, state: List<V>) : Filter<List<V>>(name, state)
|
||||
abstract class Group<V>(
|
||||
name: String,
|
||||
state: List<V>,
|
||||
) : Filter<List<V>>(name, state)
|
||||
|
||||
abstract class Sort(name: String, val values: Array<String>, state: Selection? = null) :
|
||||
Filter<Sort.Selection?>(name, state) {
|
||||
data class Selection(val index: Int, val ascending: Boolean)
|
||||
abstract class Sort(
|
||||
name: String,
|
||||
val values: Array<String>,
|
||||
state: Selection? = null,
|
||||
) : Filter<Sort.Selection?>(name, state) {
|
||||
data class Selection(
|
||||
val index: Int,
|
||||
val ascending: Boolean,
|
||||
)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package eu.kanade.tachiyomi.source.model
|
||||
|
||||
data class FilterList(val list: List<Filter<*>>) : List<Filter<*>> by list {
|
||||
data class FilterList(
|
||||
val list: List<Filter<*>>,
|
||||
) : List<Filter<*>> by list {
|
||||
constructor(vararg fs: Filter<*>) : this(if (fs.isNotEmpty()) fs.asList() else emptyList())
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
package eu.kanade.tachiyomi.source.model
|
||||
|
||||
data class MangasPage(val mangas: List<SManga>, val hasNextPage: Boolean)
|
||||
data class MangasPage(
|
||||
val mangas: List<SManga>,
|
||||
val hasNextPage: Boolean,
|
||||
)
|
||||
|
||||
@@ -24,8 +24,6 @@ interface SChapter : Serializable {
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun create(): SChapter {
|
||||
return SChapterImpl()
|
||||
}
|
||||
fun create(): SChapter = SChapterImpl()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,9 +62,7 @@ interface SManga : Serializable {
|
||||
const val CANCELLED = 5
|
||||
const val ON_HIATUS = 6
|
||||
|
||||
fun create(): SManga {
|
||||
return SMangaImpl()
|
||||
}
|
||||
fun create(): SManga = SMangaImpl()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,9 +66,7 @@ abstract class HttpSource : CatalogueSource {
|
||||
open val client: OkHttpClient
|
||||
get() = network.client
|
||||
|
||||
private fun generateId(): Long {
|
||||
return generateId("${name.lowercase()}/$lang/$versionId")
|
||||
}
|
||||
private fun generateId(): Long = generateId("${name.lowercase()}/$lang/$versionId")
|
||||
|
||||
/**
|
||||
* Generates a unique ID for the source based on the provided [name], [lang] and
|
||||
@@ -121,13 +119,13 @@ abstract class HttpSource : CatalogueSource {
|
||||
* @param page the page number to retrieve.
|
||||
*/
|
||||
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getPopularManga"))
|
||||
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
|
||||
return client.newCall(popularMangaRequest(page))
|
||||
override fun fetchPopularManga(page: Int): Observable<MangasPage> =
|
||||
client
|
||||
.newCall(popularMangaRequest(page))
|
||||
.asObservableSuccess()
|
||||
.map { response ->
|
||||
popularMangaParse(response)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request for the popular manga given the page.
|
||||
@@ -156,20 +154,19 @@ abstract class HttpSource : CatalogueSource {
|
||||
page: Int,
|
||||
query: String,
|
||||
filters: FilterList,
|
||||
): Observable<MangasPage> {
|
||||
return Observable.defer {
|
||||
try {
|
||||
client.newCall(searchMangaRequest(page, query, filters)).asObservableSuccess()
|
||||
} catch (e: NoClassDefFoundError) {
|
||||
// RxJava doesn't handle Errors, which tends to happen during global searches
|
||||
// if an old extension using non-existent classes is still around
|
||||
throw RuntimeException(e)
|
||||
}
|
||||
}
|
||||
.map { response ->
|
||||
): Observable<MangasPage> =
|
||||
Observable
|
||||
.defer {
|
||||
try {
|
||||
client.newCall(searchMangaRequest(page, query, filters)).asObservableSuccess()
|
||||
} catch (e: NoClassDefFoundError) {
|
||||
// RxJava doesn't handle Errors, which tends to happen during global searches
|
||||
// if an old extension using non-existent classes is still around
|
||||
throw RuntimeException(e)
|
||||
}
|
||||
}.map { response ->
|
||||
searchMangaParse(response)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request for the search manga given the page.
|
||||
@@ -197,13 +194,13 @@ abstract class HttpSource : CatalogueSource {
|
||||
* @param page the page number to retrieve.
|
||||
*/
|
||||
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getLatestUpdates"))
|
||||
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> {
|
||||
return client.newCall(latestUpdatesRequest(page))
|
||||
override fun fetchLatestUpdates(page: Int): Observable<MangasPage> =
|
||||
client
|
||||
.newCall(latestUpdatesRequest(page))
|
||||
.asObservableSuccess()
|
||||
.map { response ->
|
||||
latestUpdatesParse(response)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request for latest manga given the page.
|
||||
@@ -227,18 +224,16 @@ abstract class HttpSource : CatalogueSource {
|
||||
* @return the updated manga.
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
override suspend fun getMangaDetails(manga: SManga): SManga {
|
||||
return fetchMangaDetails(manga).awaitSingle()
|
||||
}
|
||||
override suspend fun getMangaDetails(manga: SManga): SManga = fetchMangaDetails(manga).awaitSingle()
|
||||
|
||||
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getMangaDetails"))
|
||||
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
|
||||
return client.newCall(mangaDetailsRequest(manga))
|
||||
override fun fetchMangaDetails(manga: SManga): Observable<SManga> =
|
||||
client
|
||||
.newCall(mangaDetailsRequest(manga))
|
||||
.asObservableSuccess()
|
||||
.map { response ->
|
||||
mangaDetailsParse(response).apply { initialized = true }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request for the details of a manga. Override only if it's needed to change the
|
||||
@@ -246,9 +241,7 @@ abstract class HttpSource : CatalogueSource {
|
||||
*
|
||||
* @param manga the manga to be updated.
|
||||
*/
|
||||
open fun mangaDetailsRequest(manga: SManga): Request {
|
||||
return GET(baseUrl + manga.url, headers)
|
||||
}
|
||||
open fun mangaDetailsRequest(manga: SManga): Request = GET(baseUrl + manga.url, headers)
|
||||
|
||||
/**
|
||||
* Parses the response from the site and returns the details of a manga.
|
||||
@@ -275,9 +268,10 @@ abstract class HttpSource : CatalogueSource {
|
||||
}
|
||||
|
||||
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getChapterList"))
|
||||
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
|
||||
return if (manga.status != SManga.LICENSED) {
|
||||
client.newCall(chapterListRequest(manga))
|
||||
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> =
|
||||
if (manga.status != SManga.LICENSED) {
|
||||
client
|
||||
.newCall(chapterListRequest(manga))
|
||||
.asObservableSuccess()
|
||||
.map { response ->
|
||||
chapterListParse(response)
|
||||
@@ -285,7 +279,6 @@ abstract class HttpSource : CatalogueSource {
|
||||
} else {
|
||||
Observable.error(LicensedMangaChaptersException())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request for updating the chapter list. Override only if it's needed to override
|
||||
@@ -293,9 +286,7 @@ abstract class HttpSource : CatalogueSource {
|
||||
*
|
||||
* @param manga the manga to look for chapters.
|
||||
*/
|
||||
protected open fun chapterListRequest(manga: SManga): Request {
|
||||
return GET(baseUrl + manga.url, headers)
|
||||
}
|
||||
protected open fun chapterListRequest(manga: SManga): Request = GET(baseUrl + manga.url, headers)
|
||||
|
||||
/**
|
||||
* Parses the response from the site and returns a list of chapters.
|
||||
@@ -312,18 +303,16 @@ abstract class HttpSource : CatalogueSource {
|
||||
* @return the pages for the chapter.
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
override suspend fun getPageList(chapter: SChapter): List<Page> {
|
||||
return fetchPageList(chapter).awaitSingle()
|
||||
}
|
||||
override suspend fun getPageList(chapter: SChapter): List<Page> = fetchPageList(chapter).awaitSingle()
|
||||
|
||||
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getPageList"))
|
||||
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
||||
return client.newCall(pageListRequest(chapter))
|
||||
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> =
|
||||
client
|
||||
.newCall(pageListRequest(chapter))
|
||||
.asObservableSuccess()
|
||||
.map { response ->
|
||||
pageListParse(response)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request for getting the page list. Override only if it's needed to override the
|
||||
@@ -331,9 +320,7 @@ abstract class HttpSource : CatalogueSource {
|
||||
*
|
||||
* @param chapter the chapter whose page list has to be fetched.
|
||||
*/
|
||||
protected open fun pageListRequest(chapter: SChapter): Request {
|
||||
return GET(baseUrl + chapter.url, headers)
|
||||
}
|
||||
protected open fun pageListRequest(chapter: SChapter): Request = GET(baseUrl + chapter.url, headers)
|
||||
|
||||
/**
|
||||
* Parses the response from the site and returns a list of pages.
|
||||
@@ -350,16 +337,14 @@ abstract class HttpSource : CatalogueSource {
|
||||
* @param page the page whose source image has to be fetched.
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
open suspend fun getImageUrl(page: Page): String {
|
||||
return fetchImageUrl(page).awaitSingle()
|
||||
}
|
||||
open suspend fun getImageUrl(page: Page): String = fetchImageUrl(page).awaitSingle()
|
||||
|
||||
@Deprecated("Use the non-RxJava API instead", replaceWith = ReplaceWith("getImageUrl"))
|
||||
open fun fetchImageUrl(page: Page): Observable<String> {
|
||||
return client.newCall(imageUrlRequest(page))
|
||||
open fun fetchImageUrl(page: Page): Observable<String> =
|
||||
client
|
||||
.newCall(imageUrlRequest(page))
|
||||
.asObservableSuccess()
|
||||
.map { imageUrlParse(it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request for getting the url to the source image. Override only if it's needed to
|
||||
@@ -367,9 +352,7 @@ abstract class HttpSource : CatalogueSource {
|
||||
*
|
||||
* @param page the chapter whose page list has to be fetched
|
||||
*/
|
||||
protected open fun imageUrlRequest(page: Page): Request {
|
||||
return GET(page.url, headers)
|
||||
}
|
||||
protected open fun imageUrlRequest(page: Page): Request = GET(page.url, headers)
|
||||
|
||||
/**
|
||||
* Parses the response from the site and returns the absolute url to the source image.
|
||||
@@ -385,10 +368,10 @@ abstract class HttpSource : CatalogueSource {
|
||||
* @since extensions-lib 1.5
|
||||
* @param page the page whose source image has to be downloaded.
|
||||
*/
|
||||
open suspend fun getImage(page: Page): Response {
|
||||
return client.newCachelessCallWithProgress(imageRequest(page), page)
|
||||
open suspend fun getImage(page: Page): Response =
|
||||
client
|
||||
.newCachelessCallWithProgress(imageRequest(page), page)
|
||||
.awaitSuccess()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request for getting the source image. Override only if it's needed to override
|
||||
@@ -396,9 +379,7 @@ abstract class HttpSource : CatalogueSource {
|
||||
*
|
||||
* @param page the chapter whose page list has to be fetched
|
||||
*/
|
||||
protected open fun imageRequest(page: Page): Request {
|
||||
return GET(page.imageUrl!!, headers)
|
||||
}
|
||||
protected open fun imageRequest(page: Page): Request = GET(page.imageUrl!!, headers)
|
||||
|
||||
/**
|
||||
* Assigns the url of the chapter without the scheme and domain. It saves some redundancy from
|
||||
@@ -425,8 +406,8 @@ abstract class HttpSource : CatalogueSource {
|
||||
*
|
||||
* @param orig the full url.
|
||||
*/
|
||||
private fun getUrlWithoutDomain(orig: String): String {
|
||||
return try {
|
||||
private fun getUrlWithoutDomain(orig: String): String =
|
||||
try {
|
||||
val uri = URI(orig.replace(" ", "%20"))
|
||||
var out = uri.path
|
||||
if (uri.query != null) {
|
||||
@@ -439,7 +420,6 @@ abstract class HttpSource : CatalogueSource {
|
||||
} catch (e: URISyntaxException) {
|
||||
orig
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the url of the provided manga
|
||||
@@ -448,9 +428,7 @@ abstract class HttpSource : CatalogueSource {
|
||||
* @param manga the manga
|
||||
* @return url of the manga
|
||||
*/
|
||||
open fun getMangaUrl(manga: SManga): String {
|
||||
return mangaDetailsRequest(manga).url.toString()
|
||||
}
|
||||
open fun getMangaUrl(manga: SManga): String = mangaDetailsRequest(manga).url.toString()
|
||||
|
||||
/**
|
||||
* Returns the url of the provided chapter
|
||||
@@ -459,9 +437,7 @@ abstract class HttpSource : CatalogueSource {
|
||||
* @param chapter the chapter
|
||||
* @return url of the chapter
|
||||
*/
|
||||
open fun getChapterUrl(chapter: SChapter): String {
|
||||
return pageListRequest(chapter).url.toString()
|
||||
}
|
||||
open fun getChapterUrl(chapter: SChapter): String = pageListRequest(chapter).url.toString()
|
||||
|
||||
/**
|
||||
* Called before inserting a new chapter into database. Use it if you need to override chapter
|
||||
|
||||
@@ -138,9 +138,7 @@ abstract class ParsedHttpSource : HttpSource() {
|
||||
*
|
||||
* @param response the response from the site.
|
||||
*/
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
return mangaDetailsParse(response.asJsoup())
|
||||
}
|
||||
override fun mangaDetailsParse(response: Response): SManga = mangaDetailsParse(response.asJsoup())
|
||||
|
||||
/**
|
||||
* Returns the details of the manga from the given [document].
|
||||
@@ -176,9 +174,7 @@ abstract class ParsedHttpSource : HttpSource() {
|
||||
*
|
||||
* @param response the response from the site.
|
||||
*/
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
return pageListParse(response.asJsoup())
|
||||
}
|
||||
override fun pageListParse(response: Response): List<Page> = pageListParse(response.asJsoup())
|
||||
|
||||
/**
|
||||
* Returns a page list from the given document.
|
||||
@@ -192,9 +188,7 @@ abstract class ParsedHttpSource : HttpSource() {
|
||||
*
|
||||
* @param response the response from the site.
|
||||
*/
|
||||
override fun imageUrlParse(response: Response): String {
|
||||
return imageUrlParse(response.asJsoup())
|
||||
}
|
||||
override fun imageUrlParse(response: Response): String = imageUrlParse(response.asJsoup())
|
||||
|
||||
/**
|
||||
* Returns the absolute url to the source image from the document.
|
||||
|
||||
Reference in New Issue
Block a user