mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
Add support to update strategy on global update
+ Requests: add `GET(HttpUrl)` overload Starting line for Extensions on 1.5
This commit is contained in:
parent
f411eafef9
commit
34869c20bb
12 changed files with 124 additions and 14 deletions
|
@ -5,6 +5,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
||||||
import eu.kanade.tachiyomi.data.database.models.TrackImpl
|
import eu.kanade.tachiyomi.data.database.models.TrackImpl
|
||||||
import eu.kanade.tachiyomi.data.library.CustomMangaManager
|
import eu.kanade.tachiyomi.data.library.CustomMangaManager
|
||||||
|
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.protobuf.ProtoNumber
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@ -38,6 +39,7 @@ data class BackupManga(
|
||||||
@ProtoNumber(102) var brokenHistory: List<BrokenBackupHistory> = emptyList(),
|
@ProtoNumber(102) var brokenHistory: List<BrokenBackupHistory> = emptyList(),
|
||||||
@ProtoNumber(103) var viewer_flags: Int? = null,
|
@ProtoNumber(103) var viewer_flags: Int? = null,
|
||||||
@ProtoNumber(104) var history: List<BackupHistory> = emptyList(),
|
@ProtoNumber(104) var history: List<BackupHistory> = emptyList(),
|
||||||
|
@ProtoNumber(105) var updateStrategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE,
|
||||||
|
|
||||||
// SY specific values
|
// SY specific values
|
||||||
@ProtoNumber(602) var customStatus: Int = 0,
|
@ProtoNumber(602) var customStatus: Int = 0,
|
||||||
|
@ -69,6 +71,7 @@ data class BackupManga(
|
||||||
).takeIf { it != 0 }
|
).takeIf { it != 0 }
|
||||||
?: -1
|
?: -1
|
||||||
chapter_flags = this@BackupManga.chapterFlags
|
chapter_flags = this@BackupManga.chapterFlags
|
||||||
|
update_strategy = this@BackupManga.updateStrategy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,6 +125,7 @@ data class BackupManga(
|
||||||
viewer = manga.readingModeType,
|
viewer = manga.readingModeType,
|
||||||
viewer_flags = manga.viewer_flags.takeIf { it != -1 } ?: 0,
|
viewer_flags = manga.viewer_flags.takeIf { it != -1 } ?: 0,
|
||||||
chapterFlags = manga.chapter_flags,
|
chapterFlags = manga.chapter_flags,
|
||||||
|
updateStrategy = manga.update_strategy,
|
||||||
).also { backupManga ->
|
).also { backupManga ->
|
||||||
customMangaManager?.getManga(manga)?.let {
|
customMangaManager?.getManga(manga)?.let {
|
||||||
backupManga.customTitle = it.title
|
backupManga.customTitle = it.title
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package eu.kanade.tachiyomi.data.database
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||||
|
import java.util.Date
|
||||||
|
|
||||||
|
val dateAdapter = object : ColumnAdapter<Date, Long> {
|
||||||
|
override fun decode(databaseValue: Long): Date = Date(databaseValue)
|
||||||
|
override fun encode(value: Date): Long = value.time
|
||||||
|
}
|
||||||
|
|
||||||
|
private const val listOfStringsSeparator = ", "
|
||||||
|
val listOfStringsAdapter = object : ColumnAdapter<List<String>, String> {
|
||||||
|
override fun decode(databaseValue: String) =
|
||||||
|
if (databaseValue.isEmpty()) {
|
||||||
|
emptyList()
|
||||||
|
} else {
|
||||||
|
databaseValue.split(listOfStringsSeparator)
|
||||||
|
}
|
||||||
|
override fun encode(value: List<String>) = value.joinToString(separator = listOfStringsSeparator)
|
||||||
|
}
|
||||||
|
|
||||||
|
val updateStrategyAdapter = object : ColumnAdapter<UpdateStrategy, Int> {
|
||||||
|
private val enumValues by lazy { UpdateStrategy.values() }
|
||||||
|
|
||||||
|
override fun decode(databaseValue: Int): UpdateStrategy =
|
||||||
|
enumValues.getOrElse(databaseValue) { UpdateStrategy.ALWAYS_UPDATE }
|
||||||
|
|
||||||
|
override fun encode(value: UpdateStrategy): Int = value.ordinal
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ColumnAdapter<T : Any, S> {
|
||||||
|
/**
|
||||||
|
* @return [databaseValue] decoded as type [T].
|
||||||
|
*/
|
||||||
|
fun decode(databaseValue: S): T
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return [value] encoded as database type [S].
|
||||||
|
*/
|
||||||
|
fun encode(value: T): S
|
||||||
|
}
|
|
@ -20,7 +20,7 @@ class DbOpenCallback : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) {
|
||||||
/**
|
/**
|
||||||
* Version of the database.
|
* Version of the database.
|
||||||
*/
|
*/
|
||||||
const val DATABASE_VERSION = 15
|
const val DATABASE_VERSION = 16
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOpen(db: SupportSQLiteDatabase) {
|
override fun onOpen(db: SupportSQLiteDatabase) {
|
||||||
|
@ -109,6 +109,9 @@ class DbOpenCallback : SupportSQLiteOpenHelper.Callback(DATABASE_VERSION) {
|
||||||
db.execSQL(TrackTable.insertFromTempTable)
|
db.execSQL(TrackTable.insertFromTempTable)
|
||||||
db.execSQL(TrackTable.dropTempTable)
|
db.execSQL(TrackTable.dropTempTable)
|
||||||
}
|
}
|
||||||
|
if (oldVersion < 16) {
|
||||||
|
db.execSQL(MangaTable.addUpdateStrategy)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onConfigure(db: SupportSQLiteDatabase) {
|
override fun onConfigure(db: SupportSQLiteDatabase) {
|
||||||
|
|
|
@ -27,9 +27,11 @@ import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_SOURCE
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_STATUS
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_STATUS
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_THUMBNAIL_URL
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_THUMBNAIL_URL
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_TITLE
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_TITLE
|
||||||
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_UPDATE_STRATEGY
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_URL
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_URL
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_VIEWER
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable.COL_VIEWER
|
||||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable.TABLE
|
import eu.kanade.tachiyomi.data.database.tables.MangaTable.TABLE
|
||||||
|
import eu.kanade.tachiyomi.data.database.updateStrategyAdapter
|
||||||
|
|
||||||
class MangaTypeMapping : SQLiteTypeMapping<Manga>(
|
class MangaTypeMapping : SQLiteTypeMapping<Manga>(
|
||||||
MangaPutResolver(),
|
MangaPutResolver(),
|
||||||
|
@ -68,6 +70,7 @@ class MangaPutResolver : DefaultPutResolver<Manga>() {
|
||||||
put(COL_CHAPTER_FLAGS, obj.chapter_flags)
|
put(COL_CHAPTER_FLAGS, obj.chapter_flags)
|
||||||
put(COL_DATE_ADDED, obj.date_added)
|
put(COL_DATE_ADDED, obj.date_added)
|
||||||
put(COL_FILTERED_SCANLATORS, obj.filtered_scanlators)
|
put(COL_FILTERED_SCANLATORS, obj.filtered_scanlators)
|
||||||
|
put(COL_UPDATE_STRATEGY, obj.update_strategy.let(updateStrategyAdapter::encode))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +94,9 @@ interface BaseMangaGetResolver {
|
||||||
hide_title = cursor.getInt(cursor.getColumnIndex(COL_HIDE_TITLE)) == 1
|
hide_title = cursor.getInt(cursor.getColumnIndex(COL_HIDE_TITLE)) == 1
|
||||||
date_added = cursor.getLong(cursor.getColumnIndex(COL_DATE_ADDED))
|
date_added = cursor.getLong(cursor.getColumnIndex(COL_DATE_ADDED))
|
||||||
filtered_scanlators = cursor.getString(cursor.getColumnIndex(COL_FILTERED_SCANLATORS))
|
filtered_scanlators = cursor.getString(cursor.getColumnIndex(COL_FILTERED_SCANLATORS))
|
||||||
|
update_strategy = cursor.getInt(cursor.getColumnIndex(COL_UPDATE_STRATEGY)).let(
|
||||||
|
updateStrategyAdapter::decode,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadProvider
|
import eu.kanade.tachiyomi.data.download.DownloadProvider
|
||||||
import eu.kanade.tachiyomi.data.library.CustomMangaManager
|
import eu.kanade.tachiyomi.data.library.CustomMangaManager
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
open class MangaImpl : Manga {
|
open class MangaImpl : Manga {
|
||||||
|
@ -68,6 +69,8 @@ open class MangaImpl : Manga {
|
||||||
|
|
||||||
override var date_added: Long = 0
|
override var date_added: Long = 0
|
||||||
|
|
||||||
|
override var update_strategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE
|
||||||
|
|
||||||
override var filtered_scanlators: String? = null
|
override var filtered_scanlators: String? = null
|
||||||
|
|
||||||
lateinit var ogTitle: String
|
lateinit var ogTitle: String
|
||||||
|
|
|
@ -46,6 +46,8 @@ object MangaTable {
|
||||||
|
|
||||||
const val COL_FILTERED_SCANLATORS = "filtered_scanlators"
|
const val COL_FILTERED_SCANLATORS = "filtered_scanlators"
|
||||||
|
|
||||||
|
const val COL_UPDATE_STRATEGY = "update_strategy"
|
||||||
|
|
||||||
val createTableQuery: String
|
val createTableQuery: String
|
||||||
get() =
|
get() =
|
||||||
"""CREATE TABLE $TABLE(
|
"""CREATE TABLE $TABLE(
|
||||||
|
@ -66,7 +68,8 @@ object MangaTable {
|
||||||
$COL_HIDE_TITLE INTEGER NOT NULL,
|
$COL_HIDE_TITLE INTEGER NOT NULL,
|
||||||
$COL_CHAPTER_FLAGS INTEGER NOT NULL,
|
$COL_CHAPTER_FLAGS INTEGER NOT NULL,
|
||||||
$COL_DATE_ADDED LONG,
|
$COL_DATE_ADDED LONG,
|
||||||
$COL_FILTERED_SCANLATORS TEXT
|
$COL_FILTERED_SCANLATORS TEXT,
|
||||||
|
$COL_UPDATE_STRATEGY INTEGER AS UpdateStrategy NOT NULL DEFAULT 0
|
||||||
|
|
||||||
)"""
|
)"""
|
||||||
|
|
||||||
|
@ -85,4 +88,7 @@ object MangaTable {
|
||||||
|
|
||||||
val addFilteredScanlators: String
|
val addFilteredScanlators: String
|
||||||
get() = "ALTER TABLE $TABLE ADD COLUMN $COL_FILTERED_SCANLATORS TEXT"
|
get() = "ALTER TABLE $TABLE ADD COLUMN $COL_FILTERED_SCANLATORS TEXT"
|
||||||
|
|
||||||
|
val addUpdateStrategy: String
|
||||||
|
get() = "ALTER TABLE $TABLE ADD COLUMN $COL_UPDATE_STRATEGY INTEGER NOT NULL DEFAULT 0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.UnmeteredSource
|
import eu.kanade.tachiyomi.source.UnmeteredSource
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
|
import eu.kanade.tachiyomi.source.model.UpdateStrategy
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
|
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
|
||||||
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithTrackServiceTwoWay
|
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithTrackServiceTwoWay
|
||||||
|
@ -300,18 +301,24 @@ class LibraryUpdateService(
|
||||||
private fun filterMangaToUpdate(mangaToAdd: List<LibraryManga>): List<LibraryManga> {
|
private fun filterMangaToUpdate(mangaToAdd: List<LibraryManga>): List<LibraryManga> {
|
||||||
val restrictions = preferences.libraryUpdateMangaRestriction().get()
|
val restrictions = preferences.libraryUpdateMangaRestriction().get()
|
||||||
return mangaToAdd.filter { manga ->
|
return mangaToAdd.filter { manga ->
|
||||||
return@filter if (MANGA_NON_COMPLETED in restrictions && manga.status == SManga.COMPLETED) {
|
when {
|
||||||
skippedUpdates[manga] = getString(R.string.skipped_reason_completed)
|
MANGA_NON_COMPLETED in restrictions && manga.status == SManga.COMPLETED -> {
|
||||||
false
|
skippedUpdates[manga] = getString(R.string.skipped_reason_completed)
|
||||||
} else if (MANGA_HAS_UNREAD in restrictions && manga.unread != 0) {
|
}
|
||||||
skippedUpdates[manga] = getString(R.string.skipped_reason_not_caught_up)
|
MANGA_HAS_UNREAD in restrictions && manga.unread != 0 -> {
|
||||||
false
|
skippedUpdates[manga] = getString(R.string.skipped_reason_not_caught_up)
|
||||||
} else if (MANGA_NON_READ in restrictions && manga.totalChapters > 0 && !manga.hasRead) {
|
}
|
||||||
skippedUpdates[manga] = getString(R.string.skipped_reason_not_started)
|
MANGA_NON_READ in restrictions && manga.totalChapters > 0 && !manga.hasRead -> {
|
||||||
false
|
skippedUpdates[manga] = getString(R.string.skipped_reason_not_started)
|
||||||
} else {
|
}
|
||||||
true
|
manga.update_strategy != UpdateStrategy.ALWAYS_UPDATE -> {
|
||||||
|
skippedUpdates[manga] = getString(R.string.skipped_reason_not_always_update)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
return@filter true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return@filter false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ internal object ExtensionLoader {
|
||||||
private const val METADATA_HAS_README = "tachiyomi.extension.hasReadme"
|
private const val METADATA_HAS_README = "tachiyomi.extension.hasReadme"
|
||||||
private const val METADATA_HAS_CHANGELOG = "tachiyomi.extension.hasChangelog"
|
private const val METADATA_HAS_CHANGELOG = "tachiyomi.extension.hasChangelog"
|
||||||
const val LIB_VERSION_MIN = 1.2
|
const val LIB_VERSION_MIN = 1.2
|
||||||
const val LIB_VERSION_MAX = 1.3
|
const val LIB_VERSION_MAX = 1.4
|
||||||
|
|
||||||
private const val PACKAGE_FLAGS = PackageManager.GET_CONFIGURATIONS or PackageManager.GET_SIGNATURES
|
private const val PACKAGE_FLAGS = PackageManager.GET_CONFIGURATIONS or PackageManager.GET_SIGNATURES
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ package eu.kanade.tachiyomi.network
|
||||||
import okhttp3.CacheControl
|
import okhttp3.CacheControl
|
||||||
import okhttp3.FormBody
|
import okhttp3.FormBody
|
||||||
import okhttp3.Headers
|
import okhttp3.Headers
|
||||||
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import java.util.concurrent.TimeUnit.MINUTES
|
import java.util.concurrent.TimeUnit.MINUTES
|
||||||
|
@ -15,6 +17,17 @@ fun GET(
|
||||||
url: String,
|
url: String,
|
||||||
headers: Headers = DEFAULT_HEADERS,
|
headers: Headers = DEFAULT_HEADERS,
|
||||||
cache: CacheControl = DEFAULT_CACHE_CONTROL,
|
cache: CacheControl = DEFAULT_CACHE_CONTROL,
|
||||||
|
): Request {
|
||||||
|
return GET(url.toHttpUrl(), headers, cache)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since extensions-lib 1.4
|
||||||
|
*/
|
||||||
|
fun GET(
|
||||||
|
url: HttpUrl,
|
||||||
|
headers: Headers = DEFAULT_HEADERS,
|
||||||
|
cache: CacheControl = DEFAULT_CACHE_CONTROL,
|
||||||
): Request {
|
): Request {
|
||||||
return Request.Builder()
|
return Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
|
|
|
@ -21,6 +21,8 @@ interface SManga : Serializable {
|
||||||
|
|
||||||
var thumbnail_url: String?
|
var thumbnail_url: String?
|
||||||
|
|
||||||
|
var update_strategy: UpdateStrategy
|
||||||
|
|
||||||
var initialized: Boolean
|
var initialized: Boolean
|
||||||
|
|
||||||
val originalTitle: String
|
val originalTitle: String
|
||||||
|
@ -59,6 +61,8 @@ interface SManga : Serializable {
|
||||||
|
|
||||||
status = other.originalStatus
|
status = other.originalStatus
|
||||||
|
|
||||||
|
update_strategy = other.update_strategy
|
||||||
|
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
initialized = other.initialized
|
initialized = other.initialized
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package eu.kanade.tachiyomi.source.model
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the update strategy for a single [SManga].
|
||||||
|
* The strategy used will only take effect on the library update.
|
||||||
|
*
|
||||||
|
* @since extensions-lib 1.4
|
||||||
|
*/
|
||||||
|
enum class UpdateStrategy {
|
||||||
|
/**
|
||||||
|
* Series marked as always update will be included in the library
|
||||||
|
* update if they aren't excluded by additional restrictions.
|
||||||
|
*/
|
||||||
|
ALWAYS_UPDATE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Series marked as only fetch once will be automatically skipped
|
||||||
|
* during library updates. Useful for cases where the series is previously
|
||||||
|
* known to be finished and have only a single chapter, for example.
|
||||||
|
*/
|
||||||
|
ONLY_FETCH_ONCE,
|
||||||
|
}
|
|
@ -211,6 +211,7 @@
|
||||||
<string name="skipped_reason_completed">Skipped because series is complete</string>
|
<string name="skipped_reason_completed">Skipped because series is complete</string>
|
||||||
<string name="skipped_reason_not_caught_up">Skipped because there are unread chapters</string>
|
<string name="skipped_reason_not_caught_up">Skipped because there are unread chapters</string>
|
||||||
<string name="skipped_reason_not_started">Skipped because no chapters are read</string>
|
<string name="skipped_reason_not_started">Skipped because no chapters are read</string>
|
||||||
|
<string name="skipped_reason_not_always_update">Skipped because series does not require updates</string>
|
||||||
<string name="channel_errors">Errors</string>
|
<string name="channel_errors">Errors</string>
|
||||||
<string name="channel_skipped">Skipped</string>
|
<string name="channel_skipped">Skipped</string>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue