Merged source stop ddos

(cherry picked from commit 0c7ceb059e24ec6711b9d2ecec1296d56f120c7b)
This commit is contained in:
Jobobby04 2022-06-03 19:06:29 -04:00
parent b3baaa18d2
commit 505a8288be

View File

@ -21,11 +21,12 @@ import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
import exh.log.xLogW import exh.log.xLogW
import exh.merged.sql.models.MergedMangaReference import exh.merged.sql.models.MergedMangaReference
import exh.source.MERGED_SOURCE_ID import exh.source.MERGED_SOURCE_ID
import exh.util.executeOnIO
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import okhttp3.Response import okhttp3.Response
import rx.Observable import rx.Observable
import tachiyomi.source.model.ChapterInfo import tachiyomi.source.model.ChapterInfo
@ -63,18 +64,27 @@ class MergedSource : HttpSource() {
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo { override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
return withIOContext { return withIOContext {
val mergedManga = db.getManga(manga.key, id).executeAsBlocking() ?: throw Exception("merged manga not in db") val mergedManga = db.getManga(manga.key, id).executeAsBlocking()
val mangaReferences = db.getMergedMangaReferences(mergedManga.id ?: throw Exception("merged manga id is null")).executeOnIO() ?: throw Exception("merged manga not in db")
if (mangaReferences.isEmpty()) throw IllegalArgumentException("Manga references are empty, info unavailable, merge is likely corrupted") val mangaReferences = db.getMergedMangaReferences(mergedManga.id!!).executeAsBlocking()
if (mangaReferences.size == 1 && .apply {
run { if (isEmpty()) {
val mangaReference = mangaReferences.firstOrNull() throw IllegalArgumentException(
mangaReference == null || mangaReference.mangaSourceId == MERGED_SOURCE_ID "Manga references are empty, info unavailable, merge is likely corrupted"
)
}
if (size == 1 && first().mangaSourceId == MERGED_SOURCE_ID) {
throw IllegalArgumentException(
"Manga references contain only the merged reference, merge is likely corrupted"
)
}
} }
) throw IllegalArgumentException("Manga references contain only the merged reference, merge is likely corrupted")
val mangaInfoReference = mangaReferences.firstOrNull { it.isInfoManga } ?: mangaReferences.firstOrNull { it.mangaId != it.mergeId } val mangaInfoReference = mangaReferences.firstOrNull { it.isInfoManga }
val dbManga = mangaInfoReference?.let { db.getManga(it.mangaUrl, it.mangaSourceId).executeOnIO()?.toMangaInfo() } ?: mangaReferences.firstOrNull { it.mangaId != it.mergeId }
val dbManga = mangaInfoReference?.run {
db.getManga(mangaUrl, mangaSourceId).executeAsBlocking()?.toMangaInfo()
}
(dbManga ?: mergedManga.toMangaInfo()).copy( (dbManga ?: mergedManga.toMangaInfo()).copy(
key = manga.key, key = manga.key,
) )
@ -143,21 +153,27 @@ class MergedSource : HttpSource() {
suspend fun fetchChaptersAndSync(manga: Manga, downloadChapters: Boolean = true): Pair<List<Chapter>, List<Chapter>> { suspend fun fetchChaptersAndSync(manga: Manga, downloadChapters: Boolean = true): Pair<List<Chapter>, List<Chapter>> {
val mangaReferences = db.getMergedMangaReferences(manga.id!!).executeAsBlocking() val mangaReferences = db.getMergedMangaReferences(manga.id!!).executeAsBlocking()
if (mangaReferences.isEmpty()) throw IllegalArgumentException("Manga references are empty, chapters unavailable, merge is likely corrupted") if (mangaReferences.isEmpty()) {
throw IllegalArgumentException("Manga references are empty, chapters unavailable, merge is likely corrupted")
}
val ifDownloadNewChapters = downloadChapters && manga.shouldDownloadNewChapters(db, preferences) val ifDownloadNewChapters = downloadChapters && manga.shouldDownloadNewChapters(db, preferences)
val semaphore = Semaphore(5)
var exception: Exception? = null var exception: Exception? = null
return supervisorScope { return supervisorScope {
mangaReferences mangaReferences
.map { .groupBy(MergedMangaReference::mangaSourceId)
.minus(MERGED_SOURCE_ID)
.map { (_, values) ->
async { async {
semaphore.withPermit {
values.map {
try { try {
if (it.mangaSourceId == MERGED_SOURCE_ID) return@async null
val (source, loadedManga, reference) = val (source, loadedManga, reference) =
it.load(db, sourceManager) it.load(db, sourceManager)
if (loadedManga != null && reference.getChapterUpdates) { if (loadedManga != null && reference.getChapterUpdates) {
val chapterList = source.getChapterList(loadedManga.toMangaInfo()) val chapterList = source.getChapterList(loadedManga.toMangaInfo())
.map { it.toSChapter() } .map(ChapterInfo::toSChapter)
val results = val results =
syncChaptersWithSource(db, chapterList, loadedManga, source) syncChaptersWithSource(db, chapterList, loadedManga, source)
if (ifDownloadNewChapters && reference.downloadChapters) { if (ifDownloadNewChapters && reference.downloadChapters) {
@ -177,7 +193,10 @@ class MergedSource : HttpSource() {
} }
} }
} }
}
}
.awaitAll() .awaitAll()
.flatten()
.let { pairs -> .let { pairs ->
pairs.flatMap { it?.first.orEmpty() } to pairs.flatMap { it?.second.orEmpty() } pairs.flatMap { it?.first.orEmpty() } to pairs.flatMap { it?.second.orEmpty() }
} }
@ -187,7 +206,7 @@ class MergedSource : HttpSource() {
} }
suspend fun MergedMangaReference.load(db: DatabaseHelper, sourceManager: SourceManager): LoadedMangaSource { suspend fun MergedMangaReference.load(db: DatabaseHelper, sourceManager: SourceManager): LoadedMangaSource {
var manga = db.getManga(mangaUrl, mangaSourceId).executeOnIO() var manga = db.getManga(mangaUrl, mangaSourceId).executeAsBlocking()
val source = sourceManager.getOrStub(manga?.source ?: mangaSourceId) val source = sourceManager.getOrStub(manga?.source ?: mangaSourceId)
if (manga == null) { if (manga == null) {
manga = Manga.create(mangaSourceId).apply { manga = Manga.create(mangaSourceId).apply {