mirror of
https://github.com/tachiyomiorg/tachiyomi-extensions-inspector.git
synced 2024-12-26 08:41:50 +01:00
add Extension stuff
This commit is contained in:
parent
960ffd222e
commit
ded9cc992b
@ -1,8 +1,17 @@
|
|||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
val compileKotlin: KotlinCompile by tasks
|
||||||
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("org.jetbrains.kotlin.jvm") version "1.4.21"
|
id("org.jetbrains.kotlin.jvm") version "1.4.21"
|
||||||
application
|
application
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
compileKotlin.kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
// gradlePluginPortal()
|
// gradlePluginPortal()
|
||||||
// google()
|
// google()
|
||||||
@ -26,13 +35,26 @@ dependencies {
|
|||||||
implementation( "com.squareup.okhttp3:okhttp-dnsoverhttps:$okhttp_version")
|
implementation( "com.squareup.okhttp3:okhttp-dnsoverhttps:$okhttp_version")
|
||||||
implementation ("com.squareup.okio:okio:2.9.0")
|
implementation ("com.squareup.okio:okio:2.9.0")
|
||||||
|
|
||||||
|
|
||||||
|
// retrofit
|
||||||
|
val retrofit_version = "2.9.0"
|
||||||
|
implementation ("com.squareup.retrofit2:retrofit:$retrofit_version")
|
||||||
|
implementation ("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0")
|
||||||
|
implementation("com.squareup.retrofit2:converter-gson:$retrofit_version")
|
||||||
|
implementation ("com.squareup.retrofit2:adapter-rxjava:$retrofit_version")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
implementation("io.reactivex:rxjava:1.3.8")
|
implementation("io.reactivex:rxjava:1.3.8")
|
||||||
// implementation 'io.reactivex:rxandroid:1.2.1'
|
// implementation 'io.reactivex:rxandroid:1.2.1'
|
||||||
// implementation ("com.jakewharton.rxrelay:rxrelay:1.2.0")
|
// implementation ("com.jakewharton.rxrelay:rxrelay:1.2.0")
|
||||||
// implementation ("com.github.pwittchen:reactivenetwork:0.13.0")
|
// implementation ("com.github.pwittchen:reactivenetwork:0.13.0")
|
||||||
|
|
||||||
implementation("org.jsoup:jsoup:1.13.1")
|
implementation( "org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.0")
|
||||||
implementation("com.google.code.gson:gson:2.8.6")
|
implementation("com.google.code.gson:gson:2.8.6")
|
||||||
|
implementation ("com.github.salomonbrys.kotson:kotson:2.5.0")
|
||||||
|
|
||||||
|
implementation("org.jsoup:jsoup:1.13.1")
|
||||||
implementation("com.github.salomonbrys.kotson:kotson:2.5.0")
|
implementation("com.github.salomonbrys.kotson:kotson:2.5.0")
|
||||||
implementation("com.squareup.duktape:duktape-android:1.3.0")
|
implementation("com.squareup.duktape:duktape-android:1.3.0")
|
||||||
|
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
package eu.kanade.tachiyomi.annoations
|
||||||
|
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
annotation class Nsfw
|
@ -0,0 +1,82 @@
|
|||||||
|
package eu.kanade.tachiyomi.extension.api
|
||||||
|
|
||||||
|
//import android.content.Context
|
||||||
|
import com.github.salomonbrys.kotson.get
|
||||||
|
import com.github.salomonbrys.kotson.int
|
||||||
|
//import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.extension.model.Extension
|
||||||
|
import eu.kanade.tachiyomi.extension.model.LoadResult
|
||||||
|
import eu.kanade.tachiyomi.extension.util.ExtensionLoader
|
||||||
|
//import kotlinx.coroutines.Dispatchers
|
||||||
|
//import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.serialization.json.JsonArray
|
||||||
|
import kotlinx.serialization.json.int
|
||||||
|
import kotlinx.serialization.json.jsonObject
|
||||||
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
|
//import uy.kohesive.injekt.injectLazy
|
||||||
|
import java.util.Date
|
||||||
|
|
||||||
|
internal class ExtensionGithubApi {
|
||||||
|
|
||||||
|
// private val preferences: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
|
suspend fun findExtensions(): List<Extension.Available> {
|
||||||
|
val service: ExtensionGithubService = ExtensionGithubService.create()
|
||||||
|
|
||||||
|
val response = service.getRepo()
|
||||||
|
return parseResponse(response)
|
||||||
|
}
|
||||||
|
|
||||||
|
// suspend fun checkForUpdates(): List<Extension.Installed> {
|
||||||
|
// val extensions = fin dExtensions()
|
||||||
|
//
|
||||||
|
//// preferences.lastExtCheck().set(Date().time)
|
||||||
|
//
|
||||||
|
// val installedExtensions = ExtensionLoader.loadExtensions(context)
|
||||||
|
// .filterIsInstance<LoadResult.Success>()
|
||||||
|
// .map { it.extension }
|
||||||
|
//
|
||||||
|
// val extensionsWithUpdate = mutableListOf<Extension.Installed>()
|
||||||
|
// for (installedExt in installedExtensions) {
|
||||||
|
// val pkgName = installedExt.pkgName
|
||||||
|
// val availableExt = extensions.find { it.pkgName == pkgName } ?: continue
|
||||||
|
//
|
||||||
|
// val hasUpdate = availableExt.versionCode > installedExt.versionCode
|
||||||
|
// if (hasUpdate) {
|
||||||
|
// extensionsWithUpdate.add(installedExt)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return extensionsWithUpdate
|
||||||
|
// }
|
||||||
|
|
||||||
|
private fun parseResponse(json: JsonArray): List<Extension.Available> {
|
||||||
|
return json
|
||||||
|
.filter { element ->
|
||||||
|
val versionName = element.jsonObject["version"]!!.jsonPrimitive.content
|
||||||
|
val libVersion = versionName.substringBeforeLast('.').toDouble()
|
||||||
|
libVersion >= ExtensionLoader.LIB_VERSION_MIN && libVersion <= ExtensionLoader.LIB_VERSION_MAX
|
||||||
|
}
|
||||||
|
.map { element ->
|
||||||
|
val name = element.jsonObject["name"]!!.jsonPrimitive.content.substringAfter("Tachiyomi: ")
|
||||||
|
val pkgName = element.jsonObject["pkg"]!!.jsonPrimitive.content
|
||||||
|
val apkName = element.jsonObject["apk"]!!.jsonPrimitive.content
|
||||||
|
val versionName = element.jsonObject["version"]!!.jsonPrimitive.content
|
||||||
|
val versionCode = element.jsonObject["code"]!!.jsonPrimitive.int
|
||||||
|
val lang = element.jsonObject["lang"]!!.jsonPrimitive.content
|
||||||
|
val nsfw = element.jsonObject["nsfw"]!!.jsonPrimitive.int == 1
|
||||||
|
val icon = "$REPO_URL_PREFIX/icon/${apkName.replace(".apk", ".png")}"
|
||||||
|
|
||||||
|
Extension.Available(name, pkgName, versionName, versionCode, lang, nsfw, apkName, icon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getApkUrl(extension: Extension.Available): String {
|
||||||
|
return "$REPO_URL_PREFIX/apk/${extension.apkName}"
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val BASE_URL = "https://raw.githubusercontent.com/"
|
||||||
|
const val REPO_URL_PREFIX = "${BASE_URL}inorichi/tachiyomi-extensions/repo/"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package eu.kanade.tachiyomi.extension.api
|
||||||
|
|
||||||
|
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
|
||||||
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.JsonArray
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.http.GET
|
||||||
|
//import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to get the extension repo listing from GitHub.
|
||||||
|
*/
|
||||||
|
interface ExtensionGithubService {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val client by lazy {
|
||||||
|
val network: NetworkHelper = NetworkHelper()
|
||||||
|
network.client.newBuilder()
|
||||||
|
.addNetworkInterceptor { chain ->
|
||||||
|
val originalResponse = chain.proceed(chain.request())
|
||||||
|
originalResponse.newBuilder()
|
||||||
|
.header("Content-Encoding", "gzip")
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun create(): ExtensionGithubService {
|
||||||
|
val adapter = Retrofit.Builder()
|
||||||
|
.baseUrl(ExtensionGithubApi.BASE_URL)
|
||||||
|
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
|
||||||
|
.client(client)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
return adapter.create(ExtensionGithubService::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET("${ExtensionGithubApi.REPO_URL_PREFIX}index.json.gz")
|
||||||
|
suspend fun getRepo(): JsonArray
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package eu.kanade.tachiyomi.extension.model
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.source.Source
|
||||||
|
|
||||||
|
sealed class Extension {
|
||||||
|
|
||||||
|
abstract val name: String
|
||||||
|
abstract val pkgName: String
|
||||||
|
abstract val versionName: String
|
||||||
|
abstract val versionCode: Int
|
||||||
|
abstract val lang: String?
|
||||||
|
abstract val isNsfw: Boolean
|
||||||
|
|
||||||
|
data class Installed(
|
||||||
|
override val name: String,
|
||||||
|
override val pkgName: String,
|
||||||
|
override val versionName: String,
|
||||||
|
override val versionCode: Int,
|
||||||
|
override val lang: String,
|
||||||
|
override val isNsfw: Boolean,
|
||||||
|
val sources: List<Source>,
|
||||||
|
val hasUpdate: Boolean = false,
|
||||||
|
val isObsolete: Boolean = false,
|
||||||
|
val isUnofficial: Boolean = false
|
||||||
|
) : Extension()
|
||||||
|
|
||||||
|
data class Available(
|
||||||
|
override val name: String,
|
||||||
|
override val pkgName: String,
|
||||||
|
override val versionName: String,
|
||||||
|
override val versionCode: Int,
|
||||||
|
override val lang: String,
|
||||||
|
override val isNsfw: Boolean,
|
||||||
|
val apkName: String,
|
||||||
|
val iconUrl: String
|
||||||
|
) : Extension()
|
||||||
|
|
||||||
|
data class Untrusted(
|
||||||
|
override val name: String,
|
||||||
|
override val pkgName: String,
|
||||||
|
override val versionName: String,
|
||||||
|
override val versionCode: Int,
|
||||||
|
val signatureHash: String,
|
||||||
|
override val lang: String? = null,
|
||||||
|
override val isNsfw: Boolean = false
|
||||||
|
) : Extension()
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package eu.kanade.tachiyomi.extension.model
|
||||||
|
|
||||||
|
enum class InstallStep {
|
||||||
|
Pending, Downloading, Installing, Installed, Error;
|
||||||
|
|
||||||
|
fun isCompleted(): Boolean {
|
||||||
|
return this == Installed || this == Error
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package eu.kanade.tachiyomi.extension.model
|
||||||
|
|
||||||
|
sealed class LoadResult {
|
||||||
|
|
||||||
|
class Success(val extension: Extension.Installed) : LoadResult()
|
||||||
|
class Untrusted(val extension: Extension.Untrusted) : LoadResult()
|
||||||
|
class Error(val message: String? = null) : LoadResult() {
|
||||||
|
constructor(exception: Throwable) : this(exception.message)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,233 @@
|
|||||||
|
package eu.kanade.tachiyomi.extension.util
|
||||||
|
|
||||||
|
//import android.annotation.SuppressLint
|
||||||
|
//import android.content.Context
|
||||||
|
//import android.content.pm.PackageInfo
|
||||||
|
//import android.content.pm.PackageManager
|
||||||
|
//import dalvik.system.PathClassLoader
|
||||||
|
import eu.kanade.tachiyomi.annoations.Nsfw
|
||||||
|
//import eu.kanade.tachiyomi.data.preference.PreferenceValues
|
||||||
|
//import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.extension.model.Extension
|
||||||
|
import eu.kanade.tachiyomi.extension.model.LoadResult
|
||||||
|
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||||
|
import eu.kanade.tachiyomi.source.Source
|
||||||
|
import eu.kanade.tachiyomi.source.SourceFactory
|
||||||
|
//import eu.kanade.tachiyomi.util.lang.Hash
|
||||||
|
//import kotlinx.coroutines.async
|
||||||
|
//import kotlinx.coroutines.runBlocking
|
||||||
|
//import timber.log.Timber
|
||||||
|
//import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that handles the loading of the extensions installed in the system.
|
||||||
|
*/
|
||||||
|
//@SuppressLint("PackageManagerGetSignatures")
|
||||||
|
internal object ExtensionLoader {
|
||||||
|
|
||||||
|
// private val preferences: PreferencesHelper by injectLazy()
|
||||||
|
// private val allowNsfwSource by lazy {
|
||||||
|
// preferences.allowNsfwSource().get()
|
||||||
|
// }
|
||||||
|
|
||||||
|
private const val EXTENSION_FEATURE = "tachiyomi.extension"
|
||||||
|
private const val METADATA_SOURCE_CLASS = "tachiyomi.extension.class"
|
||||||
|
private const val METADATA_NSFW = "tachiyomi.extension.nsfw"
|
||||||
|
const val LIB_VERSION_MIN = 1.2
|
||||||
|
const val LIB_VERSION_MAX = 1.2
|
||||||
|
|
||||||
|
// private const val PACKAGE_FLAGS = PackageManager.GET_CONFIGURATIONS or PackageManager.GET_SIGNATURES
|
||||||
|
|
||||||
|
// inorichi's key
|
||||||
|
private const val officialSignature = "7ce04da7773d41b489f4693a366c36bcd0a11fc39b547168553c285bd7348e23"
|
||||||
|
/**
|
||||||
|
* List of the trusted signatures.
|
||||||
|
*/
|
||||||
|
// var trustedSignatures = mutableSetOf<String>() + preferences.trustedSignatures().get() + officialSignature
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a list of all the installed extensions initialized concurrently.
|
||||||
|
*
|
||||||
|
* @param context The application context.
|
||||||
|
*/
|
||||||
|
// fun loadExtensions(context: Context): List<LoadResult> {
|
||||||
|
// val pkgManager = context.packageManager
|
||||||
|
// val installedPkgs = pkgManager.getInstalledPackages(PACKAGE_FLAGS)
|
||||||
|
// val extPkgs = installedPkgs.filter { isPackageAnExtension(it) }
|
||||||
|
//
|
||||||
|
// if (extPkgs.isEmpty()) return emptyList()
|
||||||
|
//
|
||||||
|
// // Load each extension concurrently and wait for completion
|
||||||
|
// return runBlocking {
|
||||||
|
// val deferred = extPkgs.map {
|
||||||
|
// async { loadExtension(context, it.packageName, it) }
|
||||||
|
// }
|
||||||
|
// deferred.map { it.await() }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to load an extension from the given package name. It checks if the extension
|
||||||
|
* contains the required feature flag before trying to load it.
|
||||||
|
*/
|
||||||
|
// fun loadExtensionFromPkgName(context: Context, pkgName: String): LoadResult {
|
||||||
|
// val pkgInfo = try {
|
||||||
|
// context.packageManager.getPackageInfo(pkgName, PACKAGE_FLAGS)
|
||||||
|
// } catch (error: PackageManager.NameNotFoundException) {
|
||||||
|
// // Unlikely, but the package may have been uninstalled at this point
|
||||||
|
// return LoadResult.Error(error)
|
||||||
|
// }
|
||||||
|
// if (!isPackageAnExtension(pkgInfo)) {
|
||||||
|
// return LoadResult.Error("Tried to load a package that wasn't a extension")
|
||||||
|
// }
|
||||||
|
// return loadExtension(context, pkgName, pkgInfo)
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads an extension given its package name.
|
||||||
|
*
|
||||||
|
* @param context The application context.
|
||||||
|
* @param pkgName The package name of the extension to load.
|
||||||
|
* @param pkgInfo The package info of the extension.
|
||||||
|
*/
|
||||||
|
// private fun loadExtension(context: Context, pkgName: String, pkgInfo: PackageInfo): LoadResult {
|
||||||
|
// val pkgManager = context.packageManager
|
||||||
|
//
|
||||||
|
// val appInfo = try {
|
||||||
|
// pkgManager.getApplicationInfo(pkgName, PackageManager.GET_META_DATA)
|
||||||
|
// } catch (error: PackageManager.NameNotFoundException) {
|
||||||
|
// // Unlikely, but the package may have been uninstalled at this point
|
||||||
|
// return LoadResult.Error(error)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val extName = pkgManager.getApplicationLabel(appInfo).toString().substringAfter("Tachiyomi: ")
|
||||||
|
// val versionName = pkgInfo.versionName
|
||||||
|
// val versionCode = pkgInfo.versionCode
|
||||||
|
//
|
||||||
|
// if (versionName.isNullOrEmpty()) {
|
||||||
|
// val exception = Exception("Missing versionName for extension $extName")
|
||||||
|
// Timber.w(exception)
|
||||||
|
// return LoadResult.Error(exception)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Validate lib version
|
||||||
|
// val libVersion = versionName.substringBeforeLast('.').toDouble()
|
||||||
|
// if (libVersion < LIB_VERSION_MIN || libVersion > LIB_VERSION_MAX) {
|
||||||
|
// val exception = Exception(
|
||||||
|
// "Lib version is $libVersion, while only versions " +
|
||||||
|
// "$LIB_VERSION_MIN to $LIB_VERSION_MAX are allowed"
|
||||||
|
// )
|
||||||
|
// Timber.w(exception)
|
||||||
|
// return LoadResult.Error(exception)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val signatureHash = getSignatureHash(pkgInfo)
|
||||||
|
//
|
||||||
|
// if (signatureHash == null) {
|
||||||
|
// return LoadResult.Error("Package $pkgName isn't signed")
|
||||||
|
// } else if (signatureHash !in trustedSignatures) {
|
||||||
|
// val extension = Extension.Untrusted(extName, pkgName, versionName, versionCode, signatureHash)
|
||||||
|
// Timber.w("Extension $pkgName isn't trusted")
|
||||||
|
// return LoadResult.Untrusted(extension)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val isNsfw = appInfo.metaData.getInt(METADATA_NSFW) == 1
|
||||||
|
// if (allowNsfwSource == PreferenceValues.NsfwAllowance.BLOCKED && isNsfw) {
|
||||||
|
// return LoadResult.Error("NSFW extension $pkgName not allowed")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val classLoader = PathClassLoader(appInfo.sourceDir, null, context.classLoader)
|
||||||
|
//
|
||||||
|
// val sources = appInfo.metaData.getString(METADATA_SOURCE_CLASS)!!
|
||||||
|
// .split(";")
|
||||||
|
// .map {
|
||||||
|
// val sourceClass = it.trim()
|
||||||
|
// if (sourceClass.startsWith(".")) {
|
||||||
|
// pkgInfo.packageName + sourceClass
|
||||||
|
// } else {
|
||||||
|
// sourceClass
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// .flatMap {
|
||||||
|
// try {
|
||||||
|
// when (val obj = Class.forName(it, false, classLoader).newInstance()) {
|
||||||
|
// is Source -> listOf(obj)
|
||||||
|
// is SourceFactory -> {
|
||||||
|
// if (isSourceNsfw(obj)) {
|
||||||
|
// emptyList()
|
||||||
|
// } else {
|
||||||
|
// obj.createSources()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else -> throw Exception("Unknown source class type! ${obj.javaClass}")
|
||||||
|
// }
|
||||||
|
// } catch (e: Throwable) {
|
||||||
|
// Timber.e(e, "Extension load error: $extName.")
|
||||||
|
// return LoadResult.Error(e)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// .filter { !isSourceNsfw(it) }
|
||||||
|
//
|
||||||
|
// val langs = sources.filterIsInstance<CatalogueSource>()
|
||||||
|
// .map { it.lang }
|
||||||
|
// .toSet()
|
||||||
|
// val lang = when (langs.size) {
|
||||||
|
// 0 -> ""
|
||||||
|
// 1 -> langs.first()
|
||||||
|
// else -> "all"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val extension = Extension.Installed(
|
||||||
|
// extName,
|
||||||
|
// pkgName,
|
||||||
|
// versionName,
|
||||||
|
// versionCode,
|
||||||
|
// lang,
|
||||||
|
// isNsfw,
|
||||||
|
// sources,
|
||||||
|
// isUnofficial = signatureHash != officialSignature
|
||||||
|
// )
|
||||||
|
// return LoadResult.Success(extension)
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given package is an extension.
|
||||||
|
*
|
||||||
|
* @param pkgInfo The package info of the application.
|
||||||
|
*/
|
||||||
|
// private fun isPackageAnExtension(pkgInfo: PackageInfo): Boolean {
|
||||||
|
// return pkgInfo.reqFeatures.orEmpty().any { it.name == EXTENSION_FEATURE }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the signature hash of the package or null if it's not signed.
|
||||||
|
*
|
||||||
|
* @param pkgInfo The package info of the application.
|
||||||
|
*/
|
||||||
|
// private fun getSignatureHash(pkgInfo: PackageInfo): String? {
|
||||||
|
// val signatures = pkgInfo.signatures
|
||||||
|
// return if (signatures != null && signatures.isNotEmpty()) {
|
||||||
|
// Hash.sha256(signatures.first().toByteArray())
|
||||||
|
// } else {
|
||||||
|
// null
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a Source or SourceFactory is annotated with @Nsfw.
|
||||||
|
*/
|
||||||
|
// private fun isSourceNsfw(clazz: Any): Boolean {
|
||||||
|
// if (allowNsfwSource == PreferenceValues.NsfwAllowance.ALLOWED) {
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (clazz !is Source && clazz !is SourceFactory) {
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Annotations are proxied, hence this janky way of checking for them
|
||||||
|
// return clazz.javaClass.annotations
|
||||||
|
// .flatMap { it.javaClass.interfaces.map { it.simpleName } }
|
||||||
|
// .firstOrNull { it == Nsfw::class.java.simpleName } != null
|
||||||
|
// }
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user