better method of detemining if a source is Nsfw
This commit is contained in:
@@ -12,7 +12,6 @@ import android.content.Context
|
|||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||||
import eu.kanade.tachiyomi.source.getPreferenceKey
|
import eu.kanade.tachiyomi.source.getPreferenceKey
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
|
||||||
import mu.KotlinLogging
|
import mu.KotlinLogging
|
||||||
import org.jetbrains.exposed.sql.select
|
import org.jetbrains.exposed.sql.select
|
||||||
import org.jetbrains.exposed.sql.selectAll
|
import org.jetbrains.exposed.sql.selectAll
|
||||||
@@ -33,34 +32,32 @@ import xyz.nulldev.androidcompat.androidimpl.CustomContext
|
|||||||
object Source {
|
object Source {
|
||||||
private val logger = KotlinLogging.logger {}
|
private val logger = KotlinLogging.logger {}
|
||||||
|
|
||||||
val HttpSource.isNsfw: Boolean
|
|
||||||
get() = this::class.annotations.any { it.toString() == "@eu.kanade.tachiyomi.annotations.Nsfw()" }
|
|
||||||
|
|
||||||
fun getSourceList(): List<SourceDataClass> {
|
fun getSourceList(): List<SourceDataClass> {
|
||||||
return transaction {
|
return transaction {
|
||||||
SourceTable.selectAll().map {
|
SourceTable.selectAll().map {
|
||||||
val httpSource = getHttpSource(it[SourceTable.id].value)
|
val httpSource = getHttpSource(it[SourceTable.id].value)
|
||||||
|
val sourceExtension = ExtensionTable.select { ExtensionTable.id eq it[SourceTable.extension] }.first()
|
||||||
|
|
||||||
SourceDataClass(
|
SourceDataClass(
|
||||||
it[SourceTable.id].value.toString(),
|
it[SourceTable.id].value.toString(),
|
||||||
it[SourceTable.name],
|
it[SourceTable.name],
|
||||||
it[SourceTable.lang],
|
it[SourceTable.lang],
|
||||||
getExtensionIconUrl(
|
getExtensionIconUrl(sourceExtension[ExtensionTable.apkName]),
|
||||||
ExtensionTable.select { ExtensionTable.id eq it[SourceTable.extension] }
|
|
||||||
.first()[ExtensionTable.apkName]
|
|
||||||
),
|
|
||||||
httpSource.supportsLatest,
|
httpSource.supportsLatest,
|
||||||
httpSource is ConfigurableSource,
|
httpSource is ConfigurableSource,
|
||||||
httpSource.isNsfw
|
it[SourceTable.isNsfw]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSource(sourceId: Long): SourceDataClass {
|
fun getSource(sourceId: Long): SourceDataClass { // all the data extracted fresh form the source instance
|
||||||
return transaction {
|
return transaction {
|
||||||
val source = SourceTable.select { SourceTable.id eq sourceId }.firstOrNull()
|
val source = SourceTable.select { SourceTable.id eq sourceId }.firstOrNull()
|
||||||
val httpSource = source?.let { getHttpSource(sourceId) }
|
val httpSource = source?.let { getHttpSource(sourceId) }
|
||||||
|
val extension = source?.let {
|
||||||
|
ExtensionTable.select { ExtensionTable.id eq source[SourceTable.extension] }.first()
|
||||||
|
}
|
||||||
|
|
||||||
SourceDataClass(
|
SourceDataClass(
|
||||||
sourceId.toString(),
|
sourceId.toString(),
|
||||||
@@ -68,13 +65,12 @@ object Source {
|
|||||||
source?.get(SourceTable.lang),
|
source?.get(SourceTable.lang),
|
||||||
source?.let {
|
source?.let {
|
||||||
getExtensionIconUrl(
|
getExtensionIconUrl(
|
||||||
ExtensionTable.select { ExtensionTable.id eq source[SourceTable.extension] }
|
extension!![ExtensionTable.apkName]
|
||||||
.first()[ExtensionTable.apkName]
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
httpSource?.supportsLatest,
|
httpSource?.supportsLatest,
|
||||||
httpSource?.let { it is ConfigurableSource },
|
httpSource?.let { it is ConfigurableSource },
|
||||||
httpSource?.isNsfw
|
source?.get(SourceTable.isNsfw)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +78,7 @@ object Source {
|
|||||||
private val context by DI.global.instance<CustomContext>()
|
private val context by DI.global.instance<CustomContext>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clients should support these types for extensions to work properly (in order of importance)
|
* Clients should support these types for extensions to work properly
|
||||||
* - EditTextPreference
|
* - EditTextPreference
|
||||||
* - SwitchPreferenceCompat
|
* - SwitchPreferenceCompat
|
||||||
* - ListPreference
|
* - ListPreference
|
||||||
|
|||||||
@@ -50,10 +50,8 @@ object Extension {
|
|||||||
private val logger = KotlinLogging.logger {}
|
private val logger = KotlinLogging.logger {}
|
||||||
private val applicationDirs by DI.global.instance<ApplicationDirs>()
|
private val applicationDirs by DI.global.instance<ApplicationDirs>()
|
||||||
|
|
||||||
data class InstallableAPK(
|
private fun Any.isNsfw(): Boolean =
|
||||||
val apkFilePath: String,
|
this::class.annotations.any { it.toString() == "@eu.kanade.tachiyomi.annotations.Nsfw()" }
|
||||||
val pkgName: String
|
|
||||||
)
|
|
||||||
|
|
||||||
suspend fun installExtension(pkgName: String): Int {
|
suspend fun installExtension(pkgName: String): Int {
|
||||||
logger.debug("Installing $pkgName")
|
logger.debug("Installing $pkgName")
|
||||||
@@ -99,7 +97,7 @@ object Extension {
|
|||||||
if (libVersion < LIB_VERSION_MIN || libVersion > LIB_VERSION_MAX) {
|
if (libVersion < LIB_VERSION_MIN || libVersion > LIB_VERSION_MAX) {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
"Lib version is $libVersion, while only versions " +
|
"Lib version is $libVersion, while only versions " +
|
||||||
"$LIB_VERSION_MIN to $LIB_VERSION_MAX are allowed"
|
"$LIB_VERSION_MIN to $LIB_VERSION_MAX are allowed"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +112,8 @@ object Extension {
|
|||||||
|
|
||||||
val isNsfw = packageInfo.applicationInfo.metaData.getString(METADATA_NSFW) == "1"
|
val isNsfw = packageInfo.applicationInfo.metaData.getString(METADATA_NSFW) == "1"
|
||||||
|
|
||||||
val className = packageInfo.packageName + packageInfo.applicationInfo.metaData.getString(METADATA_SOURCE_CLASS)
|
val className =
|
||||||
|
packageInfo.packageName + packageInfo.applicationInfo.metaData.getString(METADATA_SOURCE_CLASS)
|
||||||
|
|
||||||
logger.debug("Main class for extension is $className")
|
logger.debug("Main class for extension is $className")
|
||||||
|
|
||||||
@@ -125,10 +124,11 @@ object Extension {
|
|||||||
File(dexFilePath).delete()
|
File(dexFilePath).delete()
|
||||||
|
|
||||||
// collect sources from the extension
|
// collect sources from the extension
|
||||||
val sources: List<CatalogueSource> = when (val instance = loadExtensionSources(jarFilePath, className)) {
|
val extensionMainClassInstance = loadExtensionSources(jarFilePath, className)
|
||||||
is Source -> listOf(instance)
|
val sources: List<CatalogueSource> = when (extensionMainClassInstance) {
|
||||||
is SourceFactory -> instance.createSources()
|
is Source -> listOf(extensionMainClassInstance)
|
||||||
else -> throw RuntimeException("Unknown source class type! ${instance.javaClass}")
|
is SourceFactory -> extensionMainClassInstance.createSources()
|
||||||
|
else -> throw RuntimeException("Unknown source class type! ${extensionMainClassInstance.javaClass}")
|
||||||
}.map { it as CatalogueSource }
|
}.map { it as CatalogueSource }
|
||||||
|
|
||||||
val langs = sources.map { it.lang }.toSet()
|
val langs = sources.map { it.lang }.toSet()
|
||||||
@@ -159,7 +159,8 @@ object Extension {
|
|||||||
it[this.classFQName] = className
|
it[this.classFQName] = className
|
||||||
}
|
}
|
||||||
|
|
||||||
val extensionId = ExtensionTable.select { ExtensionTable.pkgName eq pkgName }.first()[ExtensionTable.id].value
|
val extensionId =
|
||||||
|
ExtensionTable.select { ExtensionTable.pkgName eq pkgName }.first()[ExtensionTable.id].value
|
||||||
|
|
||||||
sources.forEach { httpSource ->
|
sources.forEach { httpSource ->
|
||||||
SourceTable.insert {
|
SourceTable.insert {
|
||||||
@@ -167,8 +168,9 @@ object Extension {
|
|||||||
it[name] = httpSource.name
|
it[name] = httpSource.name
|
||||||
it[lang] = httpSource.lang
|
it[lang] = httpSource.lang
|
||||||
it[extension] = extensionId
|
it[extension] = extensionId
|
||||||
|
it[SourceTable.isNsfw] = isNsfw || extensionMainClassInstance.isNsfw()
|
||||||
}
|
}
|
||||||
logger.debug("Installed source ${httpSource.name} (${httpSource.lang}) with id:${httpSource.id}")
|
logger.debug { "Installed source ${httpSource.name} (${httpSource.lang}) with id:${httpSource.id}" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 201 // we installed successfully
|
return 201 // we installed successfully
|
||||||
@@ -234,7 +236,8 @@ object Extension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getExtensionIcon(apkName: String): Pair<InputStream, String> {
|
suspend fun getExtensionIcon(apkName: String): Pair<InputStream, String> {
|
||||||
val iconUrl = transaction { ExtensionTable.select { ExtensionTable.apkName eq apkName }.first() }[ExtensionTable.iconUrl]
|
val iconUrl =
|
||||||
|
transaction { ExtensionTable.select { ExtensionTable.apkName eq apkName }.first() }[ExtensionTable.iconUrl]
|
||||||
|
|
||||||
val saveDir = "${applicationDirs.extensionsRoot}/icon"
|
val saveDir = "${applicationDirs.extensionsRoot}/icon"
|
||||||
|
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ object PackageTools {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* loads the extension main class called $className from the jar located at $jarPath
|
* loads the extension main class called [className] from the jar located at [jarPath]
|
||||||
* It may return an instance of HttpSource or SourceFactory depending on the extension.
|
* It may return an instance of HttpSource or SourceFactory depending on the extension.
|
||||||
*/
|
*/
|
||||||
fun loadExtensionSources(jarPath: String, className: String): Any {
|
fun loadExtensionSources(jarPath: String, className: String): Any {
|
||||||
|
|||||||
@@ -15,4 +15,5 @@ object SourceTable : IdTable<Long>() {
|
|||||||
val lang = varchar("lang", 10)
|
val lang = varchar("lang", 10)
|
||||||
val extension = reference("extension", ExtensionTable)
|
val extension = reference("extension", ExtensionTable)
|
||||||
val partOfFactorySource = bool("part_of_factory_source").default(false)
|
val partOfFactorySource = bool("part_of_factory_source").default(false)
|
||||||
|
val isNsfw = bool("is_nsfw").default(false)
|
||||||
}
|
}
|
||||||
|
|||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package suwayomi.tachidesk.server.database.migration
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 de.neonew.exposed.migrations.helpers.AddColumnMigration
|
||||||
|
|
||||||
|
@Suppress("ClassName", "unused")
|
||||||
|
class M0011_SourceIsNsfw : AddColumnMigration(
|
||||||
|
"Source",
|
||||||
|
"is_nsfw",
|
||||||
|
"BOOLEAN",
|
||||||
|
"FALSE"
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user