feat: logging to file

This commit is contained in:
rebelonion 2024-03-11 03:01:08 -05:00
parent 1028ac66cb
commit dbce7c5b29
67 changed files with 475 additions and 324 deletions

View file

@ -11,7 +11,7 @@ import android.os.Environment
import android.provider.MediaStore
import ani.dantotsu.FileUrl
import ani.dantotsu.currContext
import ani.dantotsu.logger
import ani.dantotsu.util.Logger
import ani.dantotsu.media.anime.AnimeNameAdapter
import ani.dantotsu.media.manga.ImageData
import ani.dantotsu.media.manga.MangaCache
@ -129,7 +129,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
val configurableSource = extension.sources[sourceLanguage] as? ConfigurableAnimeSource
?: return false
currContext()?.let { context ->
logger("isDubAvailableSeparately: ${configurableSource.getPreferenceKey()}")
Logger.log("isDubAvailableSeparately: ${configurableSource.getPreferenceKey()}")
val sharedPreferences =
context.getSharedPreferences(
configurableSource.getPreferenceKey(),
@ -205,7 +205,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
}
return sortedEpisodes.map { SEpisodeToEpisode(it) }
} catch (e: Exception) {
logger("Exception: $e")
Logger.log("Exception: $e")
}
return emptyList()
}
@ -240,7 +240,7 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
val videos = source.getVideoList(sEpisode)
videos.map { VideoToVideoServer(it) }
} catch (e: Exception) {
logger("Exception occurred: ${e.message}")
Logger.log("Exception occurred: ${e.message}")
emptyList()
}
}
@ -260,16 +260,16 @@ class DynamicAnimeParser(extension: AnimeExtension.Installed) : AnimeParser() {
?: return emptyList())
return try {
val res = source.fetchSearchAnime(1, query, source.getFilterList()).awaitSingle()
logger("query: $query")
Logger.log("query: $query")
convertAnimesPageToShowResponse(res)
} catch (e: CloudflareBypassException) {
logger("Exception in search: $e")
Logger.log("Exception in search: $e")
withContext(Dispatchers.Main) {
snackString("Failed to bypass Cloudflare")
}
emptyList()
} catch (e: Exception) {
logger("General exception in search: $e")
Logger.log("General exception in search: $e")
emptyList()
}
}
@ -358,12 +358,12 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
val res = source.getChapterList(sManga)
val reversedRes = res.reversed()
val chapterList = reversedRes.map { SChapterToMangaChapter(it) }
logger("chapterList size: ${chapterList.size}")
logger("chapterList: ${chapterList[1].title}")
logger("chapterList: ${chapterList[1].description}")
Logger.log("chapterList size: ${chapterList.size}")
Logger.log("chapterList: ${chapterList[1].title}")
Logger.log("chapterList: ${chapterList[1].description}")
chapterList
} catch (e: Exception) {
logger("loadChapters Exception: $e")
Logger.log("loadChapters Exception: $e")
emptyList()
}
}
@ -379,7 +379,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
var imageDataList: List<ImageData> = listOf()
val ret = coroutineScope {
try {
logger("source.name " + source.name)
Logger.log("source.name " + source.name)
val res = source.getPageList(sChapter)
val reIndexedPages =
res.mapIndexed { index, page -> Page(index, page.url, page.imageUrl, page.uri) }
@ -388,7 +388,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
async(Dispatchers.IO) {
mangaCache.put(page.imageUrl ?: "", ImageData(page, source))
imageDataList += ImageData(page, source)
logger("put page: ${page.imageUrl}")
Logger.log("put page: ${page.imageUrl}")
pageToMangaImage(page)
}
}
@ -396,7 +396,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
deferreds.awaitAll()
} catch (e: Exception) {
logger("loadImages Exception: $e")
Logger.log("loadImages Exception: $e")
snackString("Failed to load images: $e")
emptyList()
}
@ -414,7 +414,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
return coroutineScope {
try {
logger("source.name " + source.name)
Logger.log("source.name " + source.name)
val res = source.getPageList(sChapter)
val reIndexedPages =
res.mapIndexed { index, page -> Page(index, page.url, page.imageUrl, page.uri) }
@ -430,7 +430,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
deferreds.awaitAll()
} catch (e: Exception) {
logger("loadImages Exception: $e")
Logger.log("loadImages Exception: $e")
snackString("Failed to load images: $e")
emptyList()
}
@ -446,8 +446,8 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
try {
// Fetch the image
val response = httpSource.getImage(page)
logger("Response: ${response.code}")
logger("Response: ${response.message}")
Logger.log("Response: ${response.code}")
Logger.log("Response: ${response.message}")
// Convert the Response to an InputStream
val inputStream = response.body.byteStream()
@ -467,7 +467,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
return@withContext bitmap
} catch (e: Exception) {
// Handle any exceptions
logger("An error occurred: ${e.message}")
Logger.log("An error occurred: ${e.message}")
return@withContext null
}
}
@ -500,7 +500,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
inputStream.close()
} catch (e: Exception) {
// Handle any exceptions
logger("An error occurred: ${e.message}")
Logger.log("An error occurred: ${e.message}")
}
}
}
@ -547,7 +547,7 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
}
} catch (e: Exception) {
// Handle exception here
logger("Exception while saving image: ${e.message}")
Logger.log("Exception while saving image: ${e.message}")
}
}
@ -562,16 +562,16 @@ class DynamicMangaParser(extension: MangaExtension.Installed) : MangaParser() {
return try {
val res = source.fetchSearchManga(1, query, source.getFilterList()).awaitSingle()
logger("res observable: $res")
Logger.log("res observable: $res")
convertMangasPageToShowResponse(res)
} catch (e: CloudflareBypassException) {
logger("Exception in search: $e")
Logger.log("Exception in search: $e")
withContext(Dispatchers.Main) {
snackString("Failed to bypass Cloudflare")
}
emptyList()
} catch (e: Exception) {
logger("General exception in search: $e")
Logger.log("General exception in search: $e")
emptyList()
}
}
@ -714,7 +714,7 @@ class VideoServerPassthrough(val videoServer: VideoServer) : VideoExtractor() {
// If the format is still undetermined, log an error
if (format == null) {
logger("Unknown video format: $videoUrl")
Logger.log("Unknown video format: $videoUrl")
format = VideoType.CONTAINER
}
val headersMap: Map<String, String> =
@ -746,7 +746,7 @@ class VideoServerPassthrough(val videoServer: VideoServer) : VideoExtractor() {
private fun headRequest(fileName: String, networkHelper: NetworkHelper): VideoType? {
return try {
logger("attempting head request for $fileName")
Logger.log("attempting head request for $fileName")
val request = Request.Builder()
.url(fileName)
.head()
@ -771,13 +771,13 @@ class VideoServerPassthrough(val videoServer: VideoServer) : VideoExtractor() {
else -> null
}
} else {
logger("failed head request for $fileName")
Logger.log("failed head request for $fileName")
null
}
}
} catch (e: Exception) {
logger("Exception in headRequest: $e")
Logger.log("Exception in headRequest: $e")
null
}

View file

@ -3,7 +3,7 @@ package ani.dantotsu.parsers
import ani.dantotsu.FileUrl
import ani.dantotsu.R
import ani.dantotsu.currContext
import ani.dantotsu.logger
import ani.dantotsu.util.Logger
import ani.dantotsu.media.Media
import ani.dantotsu.settings.saving.PrefManager
import eu.kanade.tachiyomi.animesource.model.SAnime
@ -59,11 +59,11 @@ abstract class BaseParser {
saveShowResponse(mediaObj.id, response, true)
} else {
setUserText("Searching : ${mediaObj.mainName()}")
logger("Searching : ${mediaObj.mainName()}")
Logger.log("Searching : ${mediaObj.mainName()}")
val results = search(mediaObj.mainName())
//log all results
results.forEach {
logger("Result: ${it.name}")
Logger.log("Result: ${it.name}")
}
val sortedResults = if (results.isNotEmpty()) {
results.sortedByDescending {
@ -83,7 +83,7 @@ abstract class BaseParser {
) < 100
) {
setUserText("Searching : ${mediaObj.nameRomaji}")
logger("Searching : ${mediaObj.nameRomaji}")
Logger.log("Searching : ${mediaObj.nameRomaji}")
val romajiResults = search(mediaObj.nameRomaji)
val sortedRomajiResults = if (romajiResults.isNotEmpty()) {
romajiResults.sortedByDescending {
@ -96,10 +96,10 @@ abstract class BaseParser {
emptyList()
}
val closestRomaji = sortedRomajiResults.firstOrNull()
logger("Closest match from RomajiResults: ${closestRomaji?.name ?: "None"}")
Logger.log("Closest match from RomajiResults: ${closestRomaji?.name ?: "None"}")
response = if (response == null) {
logger("No exact match found in results. Using closest match from RomajiResults.")
Logger.log("No exact match found in results. Using closest match from RomajiResults.")
closestRomaji
} else {
val romajiRatio = FuzzySearch.ratio(
@ -110,14 +110,14 @@ abstract class BaseParser {
response.name.lowercase(),
mediaObj.mainName().lowercase()
)
logger("Fuzzy ratio for closest match in results: $mainNameRatio for ${response.name.lowercase()}")
logger("Fuzzy ratio for closest match in RomajiResults: $romajiRatio for ${closestRomaji?.name?.lowercase() ?: "None"}")
Logger.log("Fuzzy ratio for closest match in results: $mainNameRatio for ${response.name.lowercase()}")
Logger.log("Fuzzy ratio for closest match in RomajiResults: $romajiRatio for ${closestRomaji?.name?.lowercase() ?: "None"}")
if (romajiRatio > mainNameRatio) {
logger("RomajiResults has a closer match. Replacing response.")
Logger.log("RomajiResults has a closer match. Replacing response.")
closestRomaji
} else {
logger("Results has a closer or equal match. Keeping existing response.")
Logger.log("Results has a closer or equal match. Keeping existing response.")
response
}
}

View file

@ -1,7 +1,7 @@
package ani.dantotsu.parsers
import ani.dantotsu.Lazier
import ani.dantotsu.logger
import ani.dantotsu.util.Logger
import ani.dantotsu.media.Media
import ani.dantotsu.media.anime.Episode
import ani.dantotsu.media.manga.MangaChapter
@ -96,7 +96,7 @@ abstract class MangaReadSources : BaseSources() {
}
//must be downloaded
if (show.sManga == null) {
logger("sManga is null")
Logger.log("sManga is null")
}
if (parser is OfflineMangaParser && show.sManga == null) {
tryWithSuspend(true) {
@ -106,11 +106,11 @@ abstract class MangaReadSources : BaseSources() {
}
}
} else {
logger("Parser is not an instance of OfflineMangaParser")
Logger.log("Parser is not an instance of OfflineMangaParser")
}
logger("map size ${map.size}")
Logger.log("map size ${map.size}")
return map
}
}

View file

@ -6,6 +6,7 @@ import ani.dantotsu.parsers.novel.DynamicNovelParser
import ani.dantotsu.parsers.novel.NovelExtension
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.util.Logger
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.first
@ -47,8 +48,8 @@ object NovelSources : NovelReadSources() {
}
private fun createParsersFromExtensions(extensions: List<NovelExtension.Installed>): List<Lazier<BaseParser>> {
Log.d("NovelSources", "createParsersFromExtensions")
Log.d("NovelSources", extensions.toString())
Logger.log("createParsersFromExtensions")
Logger.log(extensions.toString())
return extensions.map { extension ->
val name = extension.name
Lazier({ DynamicNovelParser(extension) }, name)

View file

@ -3,7 +3,7 @@ package ani.dantotsu.parsers
import android.os.Environment
import ani.dantotsu.currContext
import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.logger
import ani.dantotsu.util.Logger
import ani.dantotsu.media.manga.MangaNameAdapter
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
@ -68,7 +68,7 @@ class OfflineMangaParser : MangaParser() {
matchResult?.groups?.get(1)?.value?.toIntOrNull() ?: Int.MAX_VALUE
}
for (image in images) {
logger("imageNumber: ${image.url.url}")
Logger.log("imageNumber: ${image.url.url}")
}
return images
}

View file

@ -1,6 +1,6 @@
package ani.dantotsu.parsers
import ani.dantotsu.logger
import ani.dantotsu.util.Logger
class StringMatcher {
companion object {
@ -54,10 +54,10 @@ class StringMatcher {
val closestShowAndIndex = closestShow(target, shows)
val closestIndex = closestShowAndIndex.second
if (closestIndex == -1) {
logger("No closest show found for $target")
Logger.log("No closest show found for $target")
return shows // Return original list if no closest show found
}
logger("Closest show found for $target is ${closestShowAndIndex.first.name}")
Logger.log("Closest show found for $target is ${closestShowAndIndex.first.name}")
return listOf(shows[closestIndex]) + shows.subList(0, closestIndex) + shows.subList(
closestIndex + 1,
shows.size

View file

@ -2,7 +2,7 @@ package ani.dantotsu.parsers.novel
import android.content.Context
import ani.dantotsu.logger
import ani.dantotsu.util.Logger
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import eu.kanade.tachiyomi.extension.ExtensionUpdateNotifier
@ -14,9 +14,7 @@ import eu.kanade.tachiyomi.network.awaitSuccess
import eu.kanade.tachiyomi.network.parseAs
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import logcat.LogPriority
import tachiyomi.core.util.lang.withIOContext
import tachiyomi.core.util.system.logcat
import uy.kohesive.injekt.injectLazy
import java.util.Date
import kotlin.time.Duration.Companion.days
@ -41,20 +39,20 @@ class NovelExtensionGithubApi {
.newCall(GET("${REPO_URL_PREFIX}index.min.json"))
.awaitSuccess()
} catch (e: Throwable) {
logcat(LogPriority.ERROR, e) { "Failed to get extensions from GitHub" }
Logger.log("Failed to get extensions from GitHub")
requiresFallbackSource = true
null
}
}
val response = githubResponse ?: run {
logger("using fallback source")
Logger.log("using fallback source")
networkService.client
.newCall(GET("${FALLBACK_REPO_URL_PREFIX}index.min.json"))
.awaitSuccess()
}
logger("response: $response")
Logger.log("response: $response")
val extensions = with(json) {
response
@ -67,7 +65,7 @@ class NovelExtensionGithubApi {
/*if (extensions.size < 10) { //TODO: uncomment when more extensions are added
throw Exception()
}*/
logger("extensions: $extensions")
Logger.log("extensions: $extensions")
extensions
}
}

View file

@ -3,6 +3,7 @@ package ani.dantotsu.parsers.novel
import android.os.FileObserver
import android.util.Log
import ani.dantotsu.parsers.novel.FileObserver.fileObserver
import ani.dantotsu.util.Logger
import java.io.File
@ -22,24 +23,24 @@ class NovelExtensionFileObserver(private val listener: Listener, private val pat
override fun onEvent(event: Int, file: String?) {
Log.e("NovelExtensionFileObserver", "Event: $event")
Logger.log("Event: $event")
if (file == null) return
val fullPath = File(path, file)
when (event) {
CREATE -> {
Log.e("NovelExtensionFileObserver", "File created: $fullPath")
Logger.log("File created: $fullPath")
listener.onExtensionFileCreated(fullPath)
}
DELETE -> {
Log.e("NovelExtensionFileObserver", "File deleted: $fullPath")
Logger.log("File deleted: $fullPath")
listener.onExtensionFileDeleted(fullPath)
}
MODIFY -> {
Log.e("NovelExtensionFileObserver", "File modified: $fullPath")
Logger.log("File modified: $fullPath")
listener.onExtensionFileModified(fullPath)
}
}

View file

@ -15,13 +15,12 @@ import androidx.core.content.ContextCompat
import androidx.core.content.getSystemService
import androidx.core.net.toUri
import ani.dantotsu.snackString
import ani.dantotsu.util.Logger
import com.jakewharton.rxrelay.PublishRelay
import eu.kanade.tachiyomi.extension.InstallStep
import eu.kanade.tachiyomi.util.storage.getUriCompat
import logcat.LogPriority
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import tachiyomi.core.util.system.logcat
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
@ -77,12 +76,12 @@ internal class NovelExtensionInstaller(private val context: Context) {
val fileToDelete = File("$sourcePath/${url.toUri().lastPathSegment}")
if (fileToDelete.exists()) {
if (fileToDelete.delete()) {
Log.i("Install APK", "APK file deleted successfully.")
Logger.log("APK file deleted successfully.")
} else {
Log.e("Install APK", "Failed to delete APK file.")
Logger.log("Failed to delete APK file.")
}
} else {
Log.e("Install APK", "APK file not found.")
Logger.log("APK file not found.")
}
// Register the receiver after removing (and unregistering) the previous download
@ -161,7 +160,7 @@ internal class NovelExtensionInstaller(private val context: Context) {
// Check if source path is obtained correctly
if (sourcePath == null) {
Log.e("Install APK", "Source APK path not found.")
Logger.log("Source APK path not found.")
downloadsRelay.call(downloadId to InstallStep.Error)
return InstallStep.Error
}
@ -172,14 +171,14 @@ internal class NovelExtensionInstaller(private val context: Context) {
destinationDir.mkdirs()
}
if (destinationDir?.setWritable(true) == false) {
Log.e("Install APK", "Failed to set destinationDir to writable.")
Logger.log("Failed to set destinationDir to writable.")
downloadsRelay.call(downloadId to InstallStep.Error)
return InstallStep.Error
}
// Copy the file to the new location
copyFileToInternalStorage(sourcePath, destinationPath)
Log.i("Install APK", "APK moved to $destinationPath")
Logger.log("APK moved to $destinationPath")
downloadsRelay.call(downloadId to InstallStep.Installed)
return InstallStep.Installed
}
@ -198,9 +197,9 @@ internal class NovelExtensionInstaller(private val context: Context) {
val fileToDelete = File(apkPath)
//give write permission to the file
if (fileToDelete.exists() && !fileToDelete.canWrite()) {
Log.i("Uninstall APK", "File is not writable. Giving write permission.")
Logger.log("File is not writable. Giving write permission.")
val a = fileToDelete.setWritable(true)
Log.i("Uninstall APK", "Success: $a")
Logger.log("Success: $a")
}
//set the directory to writable
val destinationDir = File(apkPath).parentFile
@ -208,27 +207,27 @@ internal class NovelExtensionInstaller(private val context: Context) {
destinationDir.mkdirs()
}
val s = destinationDir?.setWritable(true)
Log.i("Uninstall APK", "Success destinationDir: $s")
Logger.log("Success destinationDir: $s")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try {
Files.delete(fileToDelete.toPath())
} catch (e: Exception) {
Log.e("Uninstall APK", "Failed to delete APK file.")
Log.e("Uninstall APK", e.toString())
Logger.log("Failed to delete APK file.")
Logger.log(e)
snackString("Failed to delete APK file.")
}
} else {
if (fileToDelete.exists()) {
if (fileToDelete.delete()) {
Log.i("Uninstall APK", "APK file deleted successfully.")
Logger.log("APK file deleted successfully.")
snackString("APK file deleted successfully.")
} else {
Log.e("Uninstall APK", "Failed to delete APK file.")
Logger.log("Failed to delete APK file.")
snackString("Failed to delete APK file.")
}
} else {
Log.e("Uninstall APK", "APK file not found.")
Logger.log("APK file not found.")
snackString("APK file not found.")
}
}
@ -242,9 +241,9 @@ internal class NovelExtensionInstaller(private val context: Context) {
//delete the file if it already exists
if (destination.exists()) {
if (destination.delete()) {
Log.i("File Copy", "File deleted successfully.")
Logger.log("File deleted successfully.")
} else {
Log.e("File Copy", "Failed to delete file.")
Logger.log("Failed to delete file.")
}
}
@ -262,7 +261,7 @@ internal class NovelExtensionInstaller(private val context: Context) {
outputChannel?.close()
}
Log.i("File Copy", "File copied to internal storage.")
Logger.log("File copied to internal storage.")
}
private fun getRealPathFromURI(context: Context, contentUri: Uri): String? {
@ -350,7 +349,7 @@ internal class NovelExtensionInstaller(private val context: Context) {
// Set next installation step
if (uri == null) {
logcat(LogPriority.ERROR) { "Couldn't locate downloaded APK" }
Logger.log("Couldn't locate downloaded APK")
downloadsRelay.call(id to InstallStep.Error)
return
}
@ -371,7 +370,7 @@ internal class NovelExtensionInstaller(private val context: Context) {
val uri = Uri.parse(localUri)
val path = uri.path
val pkgName = path?.substring(path.lastIndexOf('/') + 1)?.removeSuffix(".apk")
Log.i("Install APK", "Package name: $pkgName")
Logger.log("Package name: $pkgName")
return pkgName ?: ""
}
}

View file

@ -7,7 +7,7 @@ import android.content.pm.PackageManager.GET_SIGNING_CERTIFICATES
import android.os.Build
import android.util.Log
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
import ani.dantotsu.logger
import ani.dantotsu.util.Logger
import ani.dantotsu.parsers.NovelInterface
import ani.dantotsu.snackString
import dalvik.system.PathClassLoader
@ -26,21 +26,20 @@ internal object NovelExtensionLoader {
val installDir = context.getExternalFilesDir(null)?.absolutePath + "/extensions/novel/"
val results = mutableListOf<NovelLoadResult>()
//the number of files
Log.e("NovelExtensionLoader", "Loading extensions from $installDir")
Log.e(
"NovelExtensionLoader",
Logger.log("Loading extensions from $installDir")
Logger.log(
"Loading extensions from ${File(installDir).listFiles()?.size}"
)
File(installDir).setWritable(false)
File(installDir).listFiles()?.forEach {
//set the file to read only
it.setWritable(false)
Log.e("NovelExtensionLoader", "Loading extension ${it.name}")
Logger.log("Loading extension ${it.name}")
val extension = loadExtension(context, it)
if (extension is NovelLoadResult.Success) {
results.add(extension)
} else {
logger("Failed to load extension ${it.name}")
Logger.log("Failed to load extension ${it.name}")
}
}
return results
@ -62,7 +61,7 @@ internal object NovelExtensionLoader {
context.packageManager.getPackageArchiveInfo(path, 0)
} catch (error: Exception) {
// Unlikely, but the package may have been uninstalled at this point
logger("Failed to load extension $pkgName")
Logger.log("Failed to load extension $pkgName")
return NovelLoadResult.Error(Exception("Failed to load extension"))
}
return loadExtension(context, File(path))
@ -88,8 +87,8 @@ internal object NovelExtensionLoader {
val signatureHash = getSignatureHash(packageInfo)
if ((signatureHash == null) || !signatureHash.contains(officialSignature)) {
logger("Package ${packageInfo.packageName} isn't signed")
logger("signatureHash: $signatureHash")
Logger.log("Package ${packageInfo.packageName} isn't signed")
Logger.log("signatureHash: $signatureHash")
snackString("Package ${packageInfo.packageName} isn't signed")
//return NovelLoadResult.Error(Exception("Extension not signed"))
}
@ -128,12 +127,12 @@ internal object NovelExtensionLoader {
private fun loadSources(context: Context, file: File, className: String): List<NovelInterface> {
return try {
Log.e("NovelExtensionLoader", "isFileWritable: ${file.canWrite()}")
Logger.log("isFileWritable: ${file.canWrite()}")
if (file.canWrite()) {
val a = file.setWritable(false)
Log.e("NovelExtensionLoader", "success: $a")
Logger.log("success: $a")
}
Log.e("NovelExtensionLoader", "isFileWritable: ${file.canWrite()}")
Logger.log("isFileWritable: ${file.canWrite()}")
val classLoader = PathClassLoader(file.absolutePath, null, context.classLoader)
val className =
"some.random.novelextensions.${className.lowercase(Locale.getDefault())}.$className"

View file

@ -2,7 +2,7 @@ package ani.dantotsu.parsers.novel
import android.content.Context
import android.graphics.drawable.Drawable
import ani.dantotsu.logger
import ani.dantotsu.util.Logger
import ani.dantotsu.snackString
import eu.kanade.tachiyomi.extension.InstallStep
import kotlinx.coroutines.flow.MutableStateFlow
@ -70,7 +70,7 @@ class NovelExtensionManager(private val context: Context) {
val extensions: List<NovelExtension.Available> = try {
api.findExtensions()
} catch (e: Exception) {
logger("Error finding extensions: ${e.message}")
Logger.log("Error finding extensions: ${e.message}")
withUIContext { snackString("Failed to get Novel extensions list") }
emptyList()
}