komikku/app/src/main/java/exh/EXHMigrations.kt

250 lines
9.6 KiB
Kotlin
Raw Normal View History

package exh
2019-04-18 23:47:13 +02:00
import android.content.Context
2019-04-18 23:40:13 +02:00
import com.elvishew.xlog.XLog
import com.pushtorefresh.storio.sqlite.queries.Query
import com.pushtorefresh.storio.sqlite.queries.RawQuery
import eu.kanade.tachiyomi.BuildConfig
2020-04-07 04:48:22 +02:00
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
import eu.kanade.tachiyomi.data.backup.models.DHistory
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.database.resolvers.MangaUrlPutResolver
import eu.kanade.tachiyomi.data.database.tables.MangaTable
2020-04-07 04:48:22 +02:00
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
2020-04-07 04:48:22 +02:00
import eu.kanade.tachiyomi.data.updater.UpdaterJob
2020-04-13 23:53:43 +02:00
import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
2020-03-31 22:38:40 +02:00
import eu.kanade.tachiyomi.util.system.jobScheduler
2019-04-14 18:48:59 +02:00
import exh.source.BlacklistedSources
import rx.Observable
import uy.kohesive.injekt.injectLazy
2019-04-18 23:47:13 +02:00
import java.io.File
import java.net.URI
import java.net.URISyntaxException
object EXHMigrations {
private val db: DatabaseHelper by injectLazy()
2019-04-18 23:40:13 +02:00
private val logger = XLog.tag("EXHMigrations")
/**
* Performs a migration when the application is updated.
*
* @param preferences Preferences of the application.
* @return true if a migration is performed, false otherwise.
*/
fun upgrade(preferences: PreferencesHelper): Boolean {
val context = preferences.context
val oldVersion = preferences.eh_lastVersionCode().getOrDefault()
2019-04-18 23:40:13 +02:00
try {
if (oldVersion < BuildConfig.VERSION_CODE) {
2019-04-18 23:40:13 +02:00
if (oldVersion < 1) {
db.inTransaction {
// Migrate HentaiCafe source IDs
2020-05-02 06:46:24 +02:00
db.lowLevel().executeSQL(
RawQuery.builder()
.query(
"""
UPDATE ${MangaTable.TABLE}
SET ${MangaTable.COL_SOURCE} = $HENTAI_CAFE_SOURCE_ID
WHERE ${MangaTable.COL_SOURCE} = 6908
""".trimIndent()
)
2019-04-18 23:40:13 +02:00
.affectsTables(MangaTable.TABLE)
2020-05-02 06:46:24 +02:00
.build()
)
2019-04-18 23:40:13 +02:00
// Migrate nhentai URLs
val nhentaiManga = db.db.get()
2020-05-02 06:46:24 +02:00
.listOfObjects(Manga::class.java)
.withQuery(
Query.builder()
.table(MangaTable.TABLE)
.where("${MangaTable.COL_SOURCE} = $NHENTAI_SOURCE_ID")
.build()
)
.prepare()
.executeAsBlocking()
2019-04-18 23:40:13 +02:00
nhentaiManga.forEach {
it.url = getUrlWithoutDomain(it.url)
}
2019-04-18 23:40:13 +02:00
db.db.put()
2020-05-02 06:46:24 +02:00
.objects(nhentaiManga)
// Extremely slow without the resolver :/
.withPutResolver(MangaUrlPutResolver())
.prepare()
.executeAsBlocking()
2019-04-18 23:40:13 +02:00
}
}
2019-04-18 23:47:13 +02:00
// Backup database in next release
if (oldVersion < 2) {
backupDatabase(context, oldVersion)
}
2019-08-13 07:31:44 +02:00
if (oldVersion < 8405) {
db.inTransaction {
// Migrate HBrowse source IDs
2020-05-02 06:46:24 +02:00
db.lowLevel().executeSQL(
RawQuery.builder()
.query(
"""
UPDATE ${MangaTable.TABLE}
SET ${MangaTable.COL_SOURCE} = $HBROWSE_SOURCE_ID
WHERE ${MangaTable.COL_SOURCE} = 1401584337232758222
""".trimIndent()
)
2019-08-13 07:31:44 +02:00
.affectsTables(MangaTable.TABLE)
2020-05-02 06:46:24 +02:00
.build()
)
2019-08-13 07:31:44 +02:00
}
2019-08-13 07:43:07 +02:00
// Cancel old scheduler jobs with old ids
2020-04-22 23:26:46 +02:00
context.jobScheduler.cancelAll()
2019-08-13 07:31:44 +02:00
}
2020-02-22 11:12:30 +01:00
if (oldVersion < 8408) {
db.inTransaction {
// Migrate Tsumino source IDs
2020-05-02 06:46:24 +02:00
db.lowLevel().executeSQL(
RawQuery.builder()
.query(
"""
UPDATE ${MangaTable.TABLE}
SET ${MangaTable.COL_SOURCE} = $TSUMINO_SOURCE_ID
WHERE ${MangaTable.COL_SOURCE} = 6909
""".trimIndent()
)
2020-02-22 11:12:30 +01:00
.affectsTables(MangaTable.TABLE)
2020-05-02 06:46:24 +02:00
.build()
)
2020-02-22 11:12:30 +01:00
}
}
if (oldVersion < 8409) {
db.inTransaction {
// Migrate tsumino URLs
val tsuminoManga = db.db.get()
2020-04-07 04:48:22 +02:00
.listOfObjects(Manga::class.java)
.withQuery(
Query.builder()
.table(MangaTable.TABLE)
.where("${MangaTable.COL_SOURCE} = $TSUMINO_SOURCE_ID")
.build()
)
.prepare()
.executeAsBlocking()
tsuminoManga.forEach {
it.url = "/entry/"+it.url.split("/").last()
}
2020-02-22 11:12:30 +01:00
db.db.put()
2020-04-07 04:48:22 +02:00
.objects(tsuminoManga)
// Extremely slow without the resolver :/
.withPutResolver(MangaUrlPutResolver())
.prepare()
.executeAsBlocking()
}
2020-04-13 23:53:43 +02:00
}
if (oldVersion < 8410) {
// Migrate to WorkManager
UpdaterJob.setupTask(context)
2020-04-13 23:53:43 +02:00
LibraryUpdateJob.setupTask(context)
BackupCreatorJob.setupTask(context)
ExtensionUpdateJob.setupTask(context)
}
2020-02-22 11:12:30 +01:00
2019-08-13 07:31:44 +02:00
2019-07-30 01:36:16 +02:00
// TODO BE CAREFUL TO NOT FUCK UP MergedSources IF CHANGING URLs
preferences.eh_lastVersionCode().set(BuildConfig.VERSION_CODE)
2019-04-18 23:40:13 +02:00
return true
}
} catch(e: Exception) {
logger.e( "Failed to migrate app from $oldVersion -> ${BuildConfig.VERSION_CODE}!", e)
}
return false
}
fun migrateBackupEntry(backupEntry: BackupEntry): Observable<BackupEntry> {
val (manga, chapters, categories, history, tracks) = backupEntry
// Migrate HentaiCafe source IDs
if(manga.source == 6908L) {
manga.source = HENTAI_CAFE_SOURCE_ID
}
2020-02-22 11:12:30 +01:00
// Migrate Tsumino source IDs
if(manga.source == 6909L) {
manga.source = TSUMINO_SOURCE_ID
}
// Migrate nhentai URLs
if(manga.source == NHENTAI_SOURCE_ID) {
manga.url = getUrlWithoutDomain(manga.url)
}
// Allow importing of nhentai extension backups
2019-04-14 18:48:59 +02:00
if(manga.source in BlacklistedSources.NHENTAI_EXT_SOURCES) {
manga.source = NHENTAI_SOURCE_ID
}
2019-04-14 18:48:59 +02:00
// Allow importing of English PervEden extension backups
if(manga.source in BlacklistedSources.PERVEDEN_EN_EXT_SOURCES) {
manga.source = PERV_EDEN_EN_SOURCE_ID
}
// Allow importing of Italian PervEden extension backups
2019-04-14 18:48:59 +02:00
if(manga.source in BlacklistedSources.PERVEDEN_IT_EXT_SOURCES) {
manga.source = PERV_EDEN_IT_SOURCE_ID
}
2019-04-14 18:48:59 +02:00
// Allow importing of EHentai extension backups
if(manga.source in BlacklistedSources.EHENTAI_EXT_SOURCES) {
manga.source = EH_SOURCE_ID
}
return Observable.just(backupEntry)
}
2019-04-18 23:47:13 +02:00
private fun backupDatabase(context: Context, oldMigrationVersion: Int) {
val backupLocation = File(File(context.filesDir, "exh_db_bck"), "$oldMigrationVersion.bck.db")
if(backupLocation.exists()) return // Do not backup same version twice
val dbLocation = context.getDatabasePath(db.lowLevel().sqliteOpenHelper().databaseName)
try {
dbLocation.copyTo(backupLocation, overwrite = true)
} catch(t: Throwable) {
XLog.w("Failed to backup database!")
}
}
private fun getUrlWithoutDomain(orig: String): String {
return try {
val uri = URI(orig)
var out = uri.path
2020-05-02 06:46:24 +02:00
if (uri.query != null) {
out += "?" + uri.query
2020-05-02 06:46:24 +02:00
}
if (uri.fragment != null) {
out += "#" + uri.fragment
2020-05-02 06:46:24 +02:00
}
out
} catch (e: URISyntaxException) {
orig
}
}
}
data class BackupEntry(
val manga: Manga,
val chapters: List<Chapter>,
val categories: List<String>,
val history: List<DHistory>,
val tracks: List<Track>
)