Skip to content

Commit

Permalink
Merge pull request #485 from Shikkanime/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
Ziedelth authored May 23, 2024
2 parents 6181bc6 + bab437b commit 519f0a6
Show file tree
Hide file tree
Showing 15 changed files with 76 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import fr.shikkanime.utils.routes.method.Post
import fr.shikkanime.utils.routes.param.BodyParam
import fr.shikkanime.utils.routes.param.QueryParam
import io.ktor.http.*
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking

private const val ADMIN = "/admin"

Expand Down Expand Up @@ -65,8 +67,10 @@ class AdminController {
private fun login(@BodyParam parameters: Parameters): Response {
val username = parameters["username"] ?: return Response.redirect(ADMIN)
val password = parameters["password"] ?: return Response.redirect(ADMIN)
val user =
memberService.findByUsernameAndPassword(username, password) ?: return Response.redirect("$ADMIN?error=1")
val user = memberService.findByUsernameAndPassword(username, password) ?: return runBlocking {
delay(1000)
Response.redirect("$ADMIN?error=1")
}

return Response.redirect(Link.DASHBOARD.href, AbstractConverter.convert(user, TokenDto::class.java))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ enum class EpisodeType {
EPISODE,
FILM,
SPECIAL,
SUMMARY,
;
}
2 changes: 1 addition & 1 deletion src/main/kotlin/fr/shikkanime/platforms/NetflixPlatform.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class NetflixPlatform :
Episode(
countryCode = key.countryCode,
anime = animeName,
animeImage = imageWithoutParams,
animeImage = key.netflixSimulcast.image,
animeBanner = animeBanner,
animeDescription = animeDescription,
releaseDateTime = releaseDateTime,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,6 @@ class EpisodeMappingRepository : AbstractRepository<EpisodeMapping>() {
}
}

fun findAllByEpisodeType(episodeType: EpisodeType): List<EpisodeMapping> {
return inTransaction {
val cb = it.criteriaBuilder
val query = cb.createQuery(getEntityClass())
val root = query.from(getEntityClass())

query.where(cb.equal(root[EpisodeMapping_.episodeType], episodeType))

it.createQuery(query)
.resultList
}
}

fun findByAnimeEpisodeTypeSeasonNumber(
anime: Anime,
episodeType: EpisodeType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ class EpisodeVariantRepository : AbstractRepository<EpisodeVariant>() {
.where(
cb.and(
cb.notEqual(root[EpisodeVariant_.audioLocale], countryCode.locale),
cb.notEqual(root[EpisodeVariant_.mapping][EpisodeMapping_.episodeType], EpisodeType.FILM)
cb.notEqual(root[EpisodeVariant_.mapping][EpisodeMapping_.episodeType], EpisodeType.FILM),
cb.notEqual(root[EpisodeVariant_.mapping][EpisodeMapping_.episodeType], EpisodeType.SUMMARY),
)
)
.orderBy(cb.asc(root[EpisodeVariant_.mapping][EpisodeMapping_.releaseDateTime]))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fr.shikkanime.repositories

import fr.shikkanime.entities.*
import fr.shikkanime.entities.enums.EpisodeType
import jakarta.persistence.Tuple
import jakarta.persistence.criteria.JoinType
import java.util.*
Expand Down Expand Up @@ -35,6 +36,8 @@ class MemberFollowAnimeRepository : AbstractRepository<MemberFollowAnime>() {
val root = query.from(getEntityClass())
val anime = root.join(MemberFollowAnime_.anime)
val episodeMapping = anime.join(Anime_.mappings, JoinType.LEFT)
// And episode type is not SUMMARY
episodeMapping.on(cb.notEqual(episodeMapping[EpisodeMapping_.episodeType], EpisodeType.SUMMARY))
val memberFollowEpisode = episodeMapping.join(EpisodeMapping_.memberFollowEpisodes, JoinType.LEFT)
memberFollowEpisode.on(cb.equal(memberFollowEpisode[MemberFollowEpisode_.member], member))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ class EpisodeMappingService : AbstractService<EpisodeMapping, EpisodeMappingRepo

fun findAllByAnime(anime: Anime) = episodeMappingRepository.findAllByAnime(anime)

fun findAllByEpisodeType(episodeType: EpisodeType) = episodeMappingRepository.findAllByEpisodeType(episodeType)

fun findLastNumber(anime: Anime, episodeType: EpisodeType, season: Int, platform: Platform, audioLocale: String) =
episodeMappingRepository.findLastNumber(anime, episodeType, season, platform, audioLocale)

Expand Down
46 changes: 33 additions & 13 deletions src/main/kotlin/fr/shikkanime/services/ImageService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import kotlinx.coroutines.runBlocking
import java.awt.*
import java.awt.geom.RoundRectangle2D
import java.awt.image.BufferedImage
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.*
import java.net.URI
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
Expand All @@ -38,13 +36,13 @@ object ImageService {
var bytes: ByteArray = byteArrayOf(),
var originalSize: Long = 0,
var size: Long = 0,
)
) : Serializable

private val logger = LoggerFactory.getLogger(javaClass)
private val threadPool = Executors.newFixedThreadPool(2)
private val threadPool = Executors.newFixedThreadPool(4)
val cache = mutableListOf<Image>()
private val change = AtomicBoolean(false)
private const val CACHE_FILE_NUMBER = 5
private const val CACHE_FILE_NUMBER = 4

private fun toHumanReadable(bytes: Long): String {
val kiloByte = 1024L
Expand Down Expand Up @@ -85,15 +83,34 @@ object ImageService {
val cache = mutableListOf<Image>()

val take = measureTimeMillis {
val json = String(FileManager.fromGzip(file.readBytes()))
val map = ObjectParser.fromJson(json, Array<Image>::class.java).toMutableList()
cache.addAll(map)
val deserializedCache = ByteArrayInputStream(file.readBytes()).use { bais ->
ObjectInputStream(bais).use {
it.readObject() as List<Image>
}
}

cache.addAll(deserializedCache)
}

logger.info("Loaded images cache part in $take ms (${cache.size} images)")
return cache
}

private fun distributeImages(images: List<Image>, numberOfLists: Int): List<List<Image>> {
// Sort images by size in descending order for a more balanced distribution
val sortedImages = images.sortedByDescending { it.size }

// Initialize lists to hold the distributed images
val resultLists = MutableList(numberOfLists) { mutableListOf<Image>() }

// Distribute images using round-robin approach
sortedImages.forEachIndexed { index, image ->
resultLists[index % numberOfLists].add(image)
}

return resultLists
}

fun saveCache() {
if (!change.get()) {
logger.info("No changes detected in images cache")
Expand All @@ -102,9 +119,7 @@ object ImageService {

change.set(false)

val cacheSize = cache.size
val partSize = (cacheSize / CACHE_FILE_NUMBER) + 1
val parts = cache.toList().chunked(partSize + 1)
val parts = distributeImages(cache, CACHE_FILE_NUMBER)

logger.info("Saving images cache...")

Expand All @@ -131,7 +146,12 @@ object ImageService {

logger.info("Saving images cache part...")
val take = measureTimeMillis {
file.writeBytes(FileManager.toGzip(ObjectParser.toJson(cache).toByteArray()))
ByteArrayOutputStream().use { baos ->
ObjectOutputStream(baos).use { oos ->
oos.writeObject(cache)
file.writeBytes(baos.toByteArray())
}
}
}

logger.info(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import fr.shikkanime.dtos.GenericDto
import fr.shikkanime.entities.EpisodeMapping
import fr.shikkanime.entities.Member
import fr.shikkanime.entities.MemberFollowEpisode
import fr.shikkanime.entities.enums.EpisodeType
import fr.shikkanime.repositories.MemberFollowEpisodeRepository
import fr.shikkanime.utils.MapCache
import fr.shikkanime.utils.routes.Response
Expand Down Expand Up @@ -39,13 +40,14 @@ class MemberFollowEpisodeService : AbstractService<MemberFollowEpisode, MemberFo
val elements = episodeMappingService.findAllByAnime(animeService.find(anime.uuid) ?: return Response.notFound())
val list = mutableListOf<MemberFollowEpisode>()

elements.forEach { element ->
if (memberFollowEpisodeRepository.findByMemberAndEpisode(member, element) != null) {
return@forEach
}
elements.filter { it.episodeType != EpisodeType.SUMMARY }
.forEach { element ->
if (memberFollowEpisodeRepository.findByMemberAndEpisode(member, element) != null) {
return@forEach
}

list.add(save(MemberFollowEpisode(member = member, episode = element)))
}
list.add(save(MemberFollowEpisode(member = member, episode = element)))
}

member.lastUpdateDateTime = ZonedDateTime.now()
memberService.update(member)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ abstract class AbstractSocialNetwork {
return when (episodeDto.mapping.episodeType) {
EpisodeType.SPECIAL -> "L'épisode spécial"
EpisodeType.FILM -> "Le film"
EpisodeType.SUMMARY -> "L'épisode récapitulatif"
else -> "L'épisode ${episodeDto.mapping.number}"
}
}
Expand Down
35 changes: 0 additions & 35 deletions src/main/kotlin/fr/shikkanime/utils/FileManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,12 @@ import org.opencv.core.MatOfByte
import org.opencv.core.MatOfInt
import org.opencv.imgcodecs.Imgcodecs
import java.io.BufferedInputStream
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.File
import java.util.zip.GZIPInputStream
import java.util.zip.GZIPOutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream

object FileManager {
init {
OpenCV.loadLocally()
}

fun toGzip(bytes: ByteArray): ByteArray {
val byteArrayOutputStream = ByteArrayOutputStream()
val gzip = GZIPOutputStream(byteArrayOutputStream)
gzip.write(bytes)
gzip.close()
return byteArrayOutputStream.toByteArray()
}

fun fromGzip(bytes: ByteArray): ByteArray {
val gzip = GZIPInputStream(ByteArrayInputStream(bytes))
val compressed = gzip.readBytes()
gzip.close()
return compressed
}

fun encodeToWebP(image: ByteArray): ByteArray {
val matImage = Imgcodecs.imdecode(MatOfByte(*image), Imgcodecs.IMREAD_UNCHANGED)
val parameters = MatOfInt(Imgcodecs.IMWRITE_WEBP_QUALITY, 75)
Expand All @@ -45,19 +23,6 @@ object FileManager {
}
}

fun zipFiles(zipFile: File, list: List<Pair<String, ByteArray>>) {
val zipOutputStream = ZipOutputStream(zipFile.outputStream())

list.forEach { file ->
val zipEntry = ZipEntry(file.first)
zipOutputStream.putNextEntry(zipEntry)
zipOutputStream.write(file.second)
zipOutputStream.closeEntry()
}

zipOutputStream.close()
}

fun getInputStreamFromResource(resource: String): BufferedInputStream {
return try {
this.javaClass.classLoader.getResourceAsStream(resource)?.buffered()
Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/fr/shikkanime/utils/StringUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ object StringUtils {
EpisodeType.EPISODE -> "Épisode"
EpisodeType.SPECIAL -> "Spécial"
EpisodeType.FILM -> "Film"
EpisodeType.SUMMARY -> "Épisode récapitulatif"
}

val ltName = when (LangType.fromAudioLocale(episode.mapping.anime.countryCode, episode.audioLocale)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ object CrunchyrollWrapper {
"${BASE_URL}auth/v1/token",
headers = mapOf(
"Content-Type" to "application/x-www-form-urlencoded",
"Authorization" to "Basic Y3Jfd2ViOg==",
"Authorization" to "Basic YWNmYWZtNTE3aGtpZWt4Yl93bWU6MDluclZfejBUNWxVdjRyRHp5ZlJYZk0wVmlIRHQyQV8=",
"ETP-Anonymous-ID" to UUID.randomUUID().toString(),
),
body = "grant_type=client_id&client_id=offline_access"
Expand Down
22 changes: 17 additions & 5 deletions src/main/resources/templates/admin/episodes/list.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
<span x-show="episode.episodeType === 'EPISODE'">EP</span>
<span x-show="episode.episodeType === 'FILM'">MOV</span>
<span x-show="episode.episodeType === 'SPECIAL'">SP</span>
<span x-show="episode.episodeType === 'SUMMARY'">SUM</span>
<span x-text="episode.number"></span>
</td>
<td x-text="episode.description"></td>
Expand All @@ -72,8 +73,7 @@
&laquo;
</a>
</li>
<template
x-for="i in Array.from({length: 7}, (_, index) => page + index - 3).filter(i => i >= 1 && i <= maxPage)">
<template x-for="i in generatePageNumbers(page, maxPage)">
<li class="page-item" x-bind:class="{active: page === i}">
<a class="page-link" @click="setPageable(i, await getEpisodes(anime, i, invalid))"
x-text="i"></a>
Expand All @@ -92,14 +92,26 @@
</div>

<script>
function generatePageNumbers(currentPage, maxPage) {
const startPage = Math.max(1, currentPage - 3);
const endPage = Math.min(maxPage, currentPage + 3);
const pages = [];
for (let i = startPage; i <= endPage; i++) {
pages.push(i);
}
return pages;
}
async function getEpisodes(anime, page, invalid) {
let params = '?sort=lastReleaseDateTime,animeName,season,episodeType,number&desc=lastReleaseDateTime,animeName,season,episodeType,number' + (invalid ? '&status=INVALID' : '');
let params = 'sort=lastReleaseDateTime,animeName,season,episodeType,number&desc=lastReleaseDateTime,animeName,season,episodeType,number' + (invalid ? '&status=INVALID' : '');
if (anime) {
params = '?anime=' + anime;
params = 'anime=' + anime + '&' + params;
}
return await axios.get('/api/v1/episode-mappings' + params + '&page=' + (page || 1) + '&limit=9')
return await axios.get('/api/v1/episode-mappings?' + params + '&page=' + (page || 1) + '&limit=9')
.then(response => response.data);
}
</script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
<#return "Film">
<#case "SPECIAL">
<#return "Spécial">
<#case "SUMMARY">
<#return "Épisode récapitulatif">
</#switch>
</#function>

Expand Down

0 comments on commit 519f0a6

Please sign in to comment.