Skip to content

Commit

Permalink
Merge pull request #345 from Shikkanime/dev
Browse files Browse the repository at this point in the history
Delete duplicated episodes and add filter to avoid this next time
  • Loading branch information
Ziedelth authored Apr 7, 2024
2 parents ae30f70 + 31c1682 commit 57e7de9
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ class AdminEpisodeController {
return Response.template(Link.EPISODES)
}

@Path("/delete-duplicates")
@Get
@AdminSessionAuthenticated
private fun deleteDuplicates(): Response {
episodeService.deleteDuplicates()
return Response.redirect(Link.EPISODES.href)
}

@Path("/{uuid}")
@Get
@AdminSessionAuthenticated
Expand Down
31 changes: 31 additions & 0 deletions src/main/kotlin/fr/shikkanime/repositories/EpisodeRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -176,4 +176,35 @@ class EpisodeRepository : AbstractRepository<Episode>() {
.initialize()
}
}

fun isAlreadyExists(
anime: UUID,
season: Int,
episodeType: EpisodeType,
number: Int,
langType: LangType
): Boolean {
return inTransaction {
createReadOnlyQuery(
it,
"""
SELECT COUNT(*)
FROM Episode
WHERE anime.uuid = :uuid
AND season = :season
AND episodeType = :episodeType
AND number = :number
AND langType = :langType
""".trimIndent(),
Long::class.java
)
.setParameter("uuid", anime)
.setParameter("season", season)
.setParameter("episodeType", episodeType)
.setParameter("number", number)
.setParameter("langType", langType)
.resultList
.first() > 0
}
}
}
29 changes: 28 additions & 1 deletion src/main/kotlin/fr/shikkanime/services/EpisodeService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,24 @@ class EpisodeService : AbstractService<Episode, EpisodeRepository>() {
animeService.findAllByLikeName(copy.countryCode!!, copy.name!!).firstOrNull() ?: animeService.save(copy)
entity.anime = anime.copy()

if (episodeRepository.isAlreadyExists(
anime.uuid!!,
entity.season!!,
entity.episodeType!!,
entity.number!!,
entity.langType!!
)
) {
throw IllegalArgumentException("Episode already exists")
}

if (anime.banner.isNullOrBlank() && !copy.banner.isNullOrBlank()) {
anime.banner = copy.banner
}

entity.number.takeIf { it == -1 }?.let {
entity.number = episodeRepository.getLastNumber(
anime.uuid!!,
anime.uuid,
entity.platform!!,
entity.season!!,
entity.episodeType!!,
Expand Down Expand Up @@ -188,4 +199,20 @@ class EpisodeService : AbstractService<Episode, EpisodeRepository>() {
super.delete(entity)
MapCache.invalidate(Episode::class.java)
}

fun deleteDuplicates() {
val all = episodeRepository.findAll()
// Group by anime, season, episodeType, number, langType
// Filter by having count > 1
val grouped = all.groupBy { it.anime?.uuid to it.season to it.episodeType to it.number to it.langType }
val duplicates = grouped.values.filter { it.size > 1 }

duplicates.forEach { group ->
val sorted = group.sortedBy { it.releaseDateTime }
val toDelete = sorted.drop(1)
toDelete.forEach { episodeRepository.delete(it) }
}

MapCache.invalidate(Episode::class.java)
}
}
17 changes: 13 additions & 4 deletions src/main/resources/templates/admin/episodes/list.ftl
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
<#import "../_navigation.ftl" as navigation />

<@navigation.display>
<div class="row g-3 align-items-center mb-3">
<div class="col-auto">
<label class="form-label" for="animeInput">Anime UUID</label>
<input type="text" class="form-control" id="animeInput">
<div class="d-flex mb-3">
<div class="ms-0 me-auto row g-3 align-items-center">
<div class="col-auto">
<label class="form-label" for="animeInput">Anime UUID</label>
<input type="text" class="form-control" id="animeInput">
</div>
</div>

<div class="ms-auto me-0">
<a href="/admin/episodes/delete-duplicates" class="btn btn-danger">
<i class="bi bi-trash"></i>
Delete Duplicates
</a>
</div>
</div>

Expand Down

0 comments on commit 57e7de9

Please sign in to comment.