diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml
new file mode 100644
index 0000000..b820ab4
--- /dev/null
+++ b/.github/workflows/develop.yml
@@ -0,0 +1,36 @@
+name: Build
+on:
+ push:
+ branches-ignore:
+ - stable
+
+jobs:
+ build:
+ name: Build
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
+ - name: Set up JDK 11
+ uses: actions/setup-java@v1
+ with:
+ java-version: 11
+ - name: Cache SonarQube packages
+ uses: actions/cache@v1
+ with:
+ path: ~/.sonar/cache
+ key: ${{ runner.os }}-sonar
+ restore-keys: ${{ runner.os }}-sonar
+ - name: Cache Maven packages
+ uses: actions/cache@v1
+ with:
+ path: ~/.m2
+ key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
+ restore-keys: ${{ runner.os }}-m2
+ - name: Build and analyze
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+ SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
+ run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=API
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 4242c24..043427f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,11 +13,19 @@
official
1.7.20
11
- 1.4.4
+ 1.4.5
UTF-8
true
fr.ziedelth.ApplicationKt
5.9.1
+
+
+ **/fr/ziedelth/events/**,
+ **/fr/ziedelth/listeners/**,
+ **/fr/ziedelth/plugins/**,
+ **/fr/ziedelth/utils/**,
+ **/fr/ziedelth/Application.kt
+
@@ -47,6 +55,17 @@
${junit-jupiter.version}
test
+
+ com.h2database
+ h2
+ 2.1.214
+ test
+
+
+ io.ktor
+ ktor-server-test-host-jvm
+ ${ktor_version}
+
io.ktor
ktor-server-core-jvm
@@ -67,6 +86,12 @@
ktor-server-content-negotiation-jvm
${ktor_version}
+
+ io.ktor
+ ktor-client-content-negotiation-jvm
+ ${ktor_version}
+ test
+
io.ktor
ktor-serialization-gson-jvm
@@ -199,9 +224,34 @@
maven-compiler-plugin
- ${kotlin.compiler.jvmTarget}
+
+ org.sonarsource.scanner.maven
+ sonar-maven-plugin
+ 3.9.1.2184
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.8
+
+
+ prepare-agent
+
+ prepare-agent
+
+ test-compile
+
+
+ report
+
+ report
+
+ test
+
+
+
\ No newline at end of file
diff --git a/src/main/kotlin/fr/ziedelth/controllers/AbstractController.kt b/src/main/kotlin/fr/ziedelth/controllers/AbstractController.kt
new file mode 100644
index 0000000..155a0b3
--- /dev/null
+++ b/src/main/kotlin/fr/ziedelth/controllers/AbstractController.kt
@@ -0,0 +1,118 @@
+package fr.ziedelth.controllers
+
+import com.google.gson.Gson
+import fr.ziedelth.repositories.IPageRepository
+import fr.ziedelth.utils.Decoder
+import fr.ziedelth.utils.ImageCache
+import fr.ziedelth.utils.RequestCache
+import io.ktor.http.*
+import io.ktor.server.application.*
+import io.ktor.server.request.*
+import io.ktor.server.response.*
+import io.ktor.server.routing.*
+import io.ktor.util.pipeline.*
+import java.io.Serializable
+import java.lang.reflect.ParameterizedType
+import java.util.*
+
+const val UNKNOWN_MESSAGE_ERROR = "Unknown error"
+const val MISSING_PARAMETERS_MESSAGE_ERROR = "Missing parameters"
+
+open class IController(val prefix: String) {
+ val entityName: String = ((javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<*>).simpleName
+ val uuidRequest: UUID = UUID.randomUUID()
+
+ fun PipelineContext.getPageAndLimit(): Pair {
+ val page = call.parameters["page"]!!.toIntOrNull() ?: throw IllegalArgumentException("Page is not valid")
+ val limit = call.parameters["limit"]!!.toIntOrNull() ?: throw IllegalArgumentException("Limit is not valid")
+
+ if (page < 1 || limit < 1) {
+ throw IllegalArgumentException("Page or limit is not valid")
+ }
+
+ if (limit > 30) {
+ throw IllegalArgumentException("Limit is too high")
+ }
+
+ return Pair(page, limit)
+ }
+
+ suspend fun printError(call: ApplicationCall, e: Exception) {
+ e.printStackTrace()
+ call.respond(HttpStatusCode.InternalServerError, e.message ?: UNKNOWN_MESSAGE_ERROR)
+ }
+
+ protected fun Route.getWithPage(iPageRepository: IPageRepository) {
+ get("/country/{country}/page/{page}/limit/{limit}") {
+ try {
+ val country = call.parameters["country"]!!
+ val (page, limit) = getPageAndLimit()
+ println("GET $prefix/country/$country/page/$page/limit/$limit")
+ val request = RequestCache.get(uuidRequest, country, page, limit)
+
+ if (request == null || request.isExpired()) {
+ val list = iPageRepository.getByPage(country, page, limit)
+ request?.update(list) ?: RequestCache.put(uuidRequest, country, page, limit, value = list)
+ }
+
+ call.respond(RequestCache.get(uuidRequest, country, page, limit)!!.value!!)
+ } catch (e: Exception) {
+ printError(call, e)
+ }
+ }
+ }
+
+ protected fun Route.getAnimeWithPage(iPageRepository: IPageRepository) {
+ get("/anime/{uuid}/page/{page}/limit/{limit}") {
+ try {
+ val animeUuid = call.parameters["uuid"]!!
+ val (page, limit) = getPageAndLimit()
+ println("GET $prefix/anime/$animeUuid/page/$page/limit/$limit")
+ call.respond(iPageRepository.getByPageWithAnime(UUID.fromString(animeUuid), page, limit))
+ } catch (e: Exception) {
+ printError(call, e)
+ }
+ }
+ }
+
+ protected fun Route.getWatchlistWithPage(iPageRepository: IPageRepository) {
+ post("/watchlist/page/{page}/limit/{limit}") {
+ try {
+ val watchlist = call.receive()
+ val (page, limit) = getPageAndLimit()
+ println("POST $prefix/watchlist/page/$page/limit/$limit")
+ val dataFromGzip =
+ Gson().fromJson(Decoder.fromGzip(watchlist), Array::class.java).map { UUID.fromString(it) }
+ call.respond(iPageRepository.getByPageWithList(dataFromGzip, page, limit))
+ } catch (e: Exception) {
+ printError(call, e)
+ }
+ }
+ }
+
+ fun Route.getAttachment() {
+ get("/attachment/{uuid}") {
+ val string = call.parameters["uuid"]!!
+ val uuidRegex =
+ "^[0-9(a-f|A-F)]{8}-[0-9(a-f|A-F)]{4}-4[0-9(a-f|A-F)]{3}-[89ab][0-9(a-f|A-F)]{3}-[0-9(a-f|A-F)]{12}\$".toRegex()
+
+ if (!uuidRegex.matches(string)) {
+ println("GET $prefix/attachment/$string : Invalid UUID")
+ return@get call.respond(HttpStatusCode.BadRequest)
+ }
+
+ val uuid = UUID.fromString(string)
+ println("GET ${prefix}/attachment/$uuid")
+
+ if (!ImageCache.contains(uuid)) {
+ println("Attachment $uuid not found")
+ call.respond(HttpStatusCode.NoContent)
+ return@get
+ }
+
+ val image = ImageCache.get(uuid)!!
+ println("Attachment $uuid found (${image.bytes.size} bytes)")
+ call.respondBytes(image.bytes, ContentType("image", "webp"))
+ }
+ }
+}
diff --git a/src/main/kotlin/fr/ziedelth/controllers/AnimeController.kt b/src/main/kotlin/fr/ziedelth/controllers/AnimeController.kt
index 03c2831..00fb76c 100644
--- a/src/main/kotlin/fr/ziedelth/controllers/AnimeController.kt
+++ b/src/main/kotlin/fr/ziedelth/controllers/AnimeController.kt
@@ -1,10 +1,11 @@
package fr.ziedelth.controllers
-import com.google.gson.Gson
import fr.ziedelth.entities.Anime
import fr.ziedelth.entities.isNullOrNotValid
-import fr.ziedelth.utils.Database
-import fr.ziedelth.utils.Decoder
+import fr.ziedelth.repositories.AnimeRepository
+import fr.ziedelth.repositories.CountryRepository
+import fr.ziedelth.repositories.EpisodeRepository
+import fr.ziedelth.repositories.MangaRepository
import fr.ziedelth.utils.ImageCache
import fr.ziedelth.utils.RequestCache
import io.ktor.http.*
@@ -14,141 +15,61 @@ import io.ktor.server.response.*
import io.ktor.server.routing.*
import java.util.*
-object AnimeController : IController("/animes") {
- fun Routing.getAnimes() {
- route(prefix) {
+class AnimeController(
+ private val countryRepository: CountryRepository,
+ private val animeRepository: AnimeRepository,
+ private val episodeRepository: EpisodeRepository,
+ private val mangaRepository: MangaRepository
+) :
+ IController("/animes") {
+ fun getRoutes(routing: Routing) {
+ routing.route(prefix) {
search()
- getWithPage()
- getWatchlistWithPage()
+ getByPage()
+ getWatchlistWithPage(animeRepository)
getAttachment()
create()
merge()
+ diary()
}
}
private fun Route.search() {
route("/country/{country}/search") {
get("/hash/{hash}") {
- val country = call.parameters["country"] ?: return@get call.respond(HttpStatusCode.BadRequest)
- val hash = call.parameters["hash"] ?: return@get call.respond(HttpStatusCode.BadRequest)
+ val country = call.parameters["country"]!!
+ val hash = call.parameters["hash"]!!
println("GET $prefix/country/$country/search/hash/$hash")
- val session = Database.getSession()
-
- try {
- val query = session.createQuery(
- "SELECT a.uuid FROM Anime a JOIN a.hashes h WHERE a.country.tag = :tag AND h = :hash",
- UUID::class.java
- )
- query.maxResults = 1
- query.setParameter("tag", country)
- query.setParameter("hash", hash)
- val uuid = query.uniqueResult() ?: return@get call.respond(HttpStatusCode.NotFound)
- call.respond(mapOf("uuid" to uuid))
- } catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- } finally {
- session.close()
- }
+ val anime = animeRepository.findByHash(country, hash)
+ call.respond(if (anime != null) mapOf("uuid" to anime) else HttpStatusCode.NotFound)
}
get("/name/{name}") {
- val country = call.parameters["country"] ?: return@get call.respond(HttpStatusCode.BadRequest)
- val name = call.parameters["name"] ?: return@get call.respond(HttpStatusCode.BadRequest)
+ val country = call.parameters["country"]!!
+ val name = call.parameters["name"]!!
println("GET $prefix/country/$country/search/name/$name")
- val session = Database.getSession()
-
- try {
- val query = session.createQuery(
-// "FROM Anime a WHERE a.country.tag = :tag AND LOWER(name) LIKE CONCAT('%', :name, '%')",
- "SELECT DISTINCT anime FROM Episode e WHERE e.anime.country.tag = :tag AND LOWER(e.anime.name) LIKE CONCAT('%', :name, '%') ORDER BY e.anime.name",
- Anime::class.java
- )
- query.setParameter("tag", country)
- query.setParameter("name", name.lowercase())
- call.respond(query.list() ?: HttpStatusCode.NotFound)
- } catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- } finally {
- session.close()
- }
+ call.respond(animeRepository.findByName(country, name))
}
}
}
- private fun Route.getWithPage() {
+ private fun Route.getByPage() {
get("/country/{country}/simulcast/{simulcast}/page/{page}/limit/{limit}") {
- val country = call.parameters["country"] ?: return@get call.respond(HttpStatusCode.BadRequest)
- val simulcast = call.parameters["simulcast"] ?: return@get call.respond(HttpStatusCode.BadRequest)
- val page = call.parameters["page"]?.toInt() ?: return@get call.respond(HttpStatusCode.BadRequest)
- val limit = call.parameters["limit"]?.toInt() ?: return@get call.respond(HttpStatusCode.BadRequest)
- if (page < 1 || limit < 1) return@get call.respond(HttpStatusCode.BadRequest)
- if (limit > 30) return@get call.respond(HttpStatusCode.BadRequest)
- println("GET $prefix/country/$country/simulcast/$simulcast/page/$page/limit/$limit")
- val request = RequestCache.get(uuidRequest, country, page, limit, simulcast)
-
- if (request == null || request.isExpired()) {
- val session = Database.getSession()
-
- try {
- val query = session.createQuery(
- "FROM Anime a JOIN a.simulcasts s WHERE a.country.tag = :tag AND s.uuid = :simulcast ORDER BY a.name",
- Anime::class.java
- )
- query.setParameter("tag", country)
- query.setParameter("simulcast", UUID.fromString(simulcast))
- query.firstResult = (limit * page) - limit
- query.maxResults = limit
- request?.update(query.list()) ?: RequestCache.put(
- uuidRequest,
- country,
- page,
- limit,
- simulcast,
- query.list()
- )
- } catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- } finally {
- session.close()
- }
- }
-
- call.respond(
- RequestCache.get(uuidRequest, country, page, limit, simulcast)?.value ?: HttpStatusCode.NotFound
- )
- }
- }
-
- private fun Route.getWatchlistWithPage() {
- post("/watchlist/page/{page}/limit/{limit}") {
- val watchlist = call.receive()
- val page = call.parameters["page"]?.toInt() ?: return@post call.respond(HttpStatusCode.BadRequest)
- val limit = call.parameters["limit"]?.toInt() ?: return@post call.respond(HttpStatusCode.BadRequest)
- if (page < 1 || limit < 1) return@post call.respond(HttpStatusCode.BadRequest)
- if (limit > 30) return@post call.respond(HttpStatusCode.BadRequest)
- println("POST $prefix/watchlist/page/$page/limit/$limit")
- val session = Database.getSession()
-
try {
- val dataFromGzip =
- Gson().fromJson(Decoder.fromGzip(watchlist), Array::class.java).map { UUID.fromString(it) }
+ val country = call.parameters["country"]!!
+ val simulcast = call.parameters["simulcast"]!!
+ val (page, limit) = getPageAndLimit()
+ println("GET $prefix/country/$country/simulcast/$simulcast/page/$page/limit/$limit")
+ val request = RequestCache.get(uuidRequest, country, page, limit, simulcast)
+
+ if (request == null || request.isExpired()) {
+ val list = animeRepository.getByPage(country, UUID.fromString(simulcast), page, limit)
+ request?.update(list) ?: RequestCache.put(uuidRequest, country, page, limit, simulcast, list)
+ }
- val query = session.createQuery(
- "FROM $entityName WHERE uuid IN :list ORDER BY name",
- entityClass
- )
- query.setParameter("list", dataFromGzip)
- query.firstResult = (limit * page) - limit
- query.maxResults = limit
- call.respond(query.list())
+ call.respond(RequestCache.get(uuidRequest, country, page, limit, simulcast)!!.value!!)
} catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- } finally {
- session.close()
+ printError(call, e)
}
}
}
@@ -160,8 +81,9 @@ object AnimeController : IController("/animes") {
try {
val anime = call.receive()
- anime.country = CountryController.getBy("uuid", anime.country?.uuid) ?: return@post run {
+ anime.country = countryRepository.find(anime.country!!.uuid) ?: return@post run {
println("Country not found")
+
call.respond(
HttpStatusCode.BadRequest,
"Country not found"
@@ -169,35 +91,36 @@ object AnimeController : IController("/animes") {
}
if (anime.isNullOrNotValid()) {
- println("Missing parameters")
+ println(MISSING_PARAMETERS_MESSAGE_ERROR)
println(anime)
- call.respond(HttpStatusCode.BadRequest, "Missing parameters")
+ call.respond(HttpStatusCode.BadRequest, MISSING_PARAMETERS_MESSAGE_ERROR)
return@post
}
- if (isExists("name", anime.name)) {
+ if (animeRepository.findOneByName(
+ anime.country!!.tag!!,
+ anime.name!!
+ )?.country?.uuid == anime.country!!.uuid
+ ) {
println("$entityName already exists")
call.respond(HttpStatusCode.Conflict, "$entityName already exists")
return@post
}
val hash = anime.hash()
- if (contains("hashes", hash)) {
+
+ if (animeRepository.findByHash(anime.country!!.tag!!, hash) != null) {
println("$entityName already exists")
call.respond(HttpStatusCode.Conflict, "$entityName already exists")
return@post
}
- if (!(anime.hashes.contains(hash))) {
- anime.hashes.add(hash!!)
- }
-
- val savedAnime = justSave(anime)
+ anime.hashes.add(hash)
+ val savedAnime = animeRepository.save(anime)
ImageCache.cachingNetworkImage(savedAnime.uuid, savedAnime.image!!)
call.respond(HttpStatusCode.Created, savedAnime)
} catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
+ printError(call, e)
}
}
}
@@ -208,7 +131,7 @@ object AnimeController : IController("/animes") {
val uuids = call.receive>().map { UUID.fromString(it) }
println("PUT $prefix/merge")
// Get anime
- val animes = uuids.mapNotNull { getBy("uuid", it) }
+ val animes = uuids.mapNotNull { animeRepository.find(it) }
if (animes.isEmpty()) {
println("Anime not found")
@@ -217,7 +140,7 @@ object AnimeController : IController("/animes") {
}
// Get all countries
- val countries = animes.map { it.country }.distinctBy { it?.uuid }
+ val countries = animes.map { it.country }.distinctBy { it!!.uuid }
if (countries.size > 1) {
println("Anime has different countries")
@@ -233,46 +156,45 @@ object AnimeController : IController("/animes") {
val simulcasts = animes.map { it.simulcasts }.flatten().distinctBy { it.uuid }.toMutableSet()
// Get all episodes
val episodes =
- animes.map { EpisodeController.getAllBy("anime.uuid", it.uuid) }.flatten().distinctBy { it.uuid }
+ animes.map { episodeRepository.getAllBy("anime.uuid", it.uuid) }.flatten().distinctBy { it.uuid }
.toMutableSet()
// Get all mangas
- val mangas = animes.map { MangaController.getAllBy("anime.uuid", it.uuid) }.flatten().distinctBy { it.uuid }
+ val mangas = animes.map { mangaRepository.getAllBy("anime.uuid", it.uuid) }.flatten().distinctBy { it.uuid }
.toMutableSet()
val firstAnime = animes.first()
- val mergedAnime = Anime(
- country = countries.first(),
- name = "${animes.first().name} (${animes.size})",
- releaseDate = firstAnime.releaseDate,
- image = firstAnime.image,
- description = firstAnime.description,
- hashes = hashes,
- genres = genres,
- simulcasts = simulcasts
- )
- val savedAnime = justSave(mergedAnime)
+ val savedAnime = animeRepository.find(
+ animeRepository.save(
+ Anime(
+ country = countries.first(),
+ name = "${animes.first().name} (${animes.size})",
+ releaseDate = firstAnime.releaseDate,
+ image = firstAnime.image,
+ description = firstAnime.description,
+ hashes = hashes,
+ genres = genres,
+ simulcasts = simulcasts
+ )
+ ).uuid
+ )!!
+
ImageCache.cachingNetworkImage(savedAnime.uuid, savedAnime.image!!)
- episodes.map { it.copy(anime = savedAnime) }.map { EpisodeController.justSave(it) }
- mangas.map { it.copy(anime = savedAnime) }.map { MangaController.justSave(it) }
+ episodeRepository.saveAll(episodes.map { it.copy(anime = savedAnime) })
+ mangaRepository.saveAll(mangas.map { it.copy(anime = savedAnime) })
// Delete animes
- val session = Database.getSession()
- val transaction = session.beginTransaction()
+ animeRepository.deleteAll(animes)
+ call.respond(HttpStatusCode.OK, savedAnime)
+ }
+ }
- try {
- session.createQuery("DELETE Anime WHERE uuid IN :list")
- .setParameter("list", uuids)
- .executeUpdate()
- transaction.commit()
- } catch (e: Exception) {
- e.printStackTrace()
- println("Error while deleting $prefix : ${e.message}")
- transaction.rollback()
- throw e
- } finally {
- session.close()
- }
+ private fun Route.diary() {
+ get("/diary/country/{country}/day/{day}") {
+ val country = call.parameters["country"]!!
+ val day = call.parameters["day"]!!.toIntOrNull() ?: return@get call.respond(HttpStatusCode.BadRequest)
+ println("GET $prefix/diary/country/$country/day/$day")
+ call.respond(animeRepository.getDiary(country, day))
}
}
}
diff --git a/src/main/kotlin/fr/ziedelth/controllers/CountryController.kt b/src/main/kotlin/fr/ziedelth/controllers/CountryController.kt
index 016762b..f8a4945 100644
--- a/src/main/kotlin/fr/ziedelth/controllers/CountryController.kt
+++ b/src/main/kotlin/fr/ziedelth/controllers/CountryController.kt
@@ -2,20 +2,28 @@ package fr.ziedelth.controllers
import fr.ziedelth.entities.Country
import fr.ziedelth.entities.isNullOrNotValid
+import fr.ziedelth.repositories.CountryRepository
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
-object CountryController : IController("/countries") {
- fun Routing.getCountries() {
- route(prefix) {
+class CountryController(private val countryRepository: CountryRepository) : IController("/countries") {
+ fun getRoutes(routing: Routing) {
+ routing.route(prefix) {
getAll()
create()
}
}
+ fun Route.getAll() {
+ get {
+ println("GET $prefix")
+ call.respond(countryRepository.getAll())
+ }
+ }
+
private fun Route.create() {
post {
println("POST $prefix")
@@ -24,24 +32,23 @@ object CountryController : IController("/countries") {
val country = call.receive()
if (country.isNullOrNotValid()) {
- call.respond(HttpStatusCode.BadRequest, "Missing parameters")
+ call.respond(HttpStatusCode.BadRequest, MISSING_PARAMETERS_MESSAGE_ERROR)
return@post
}
- if (isExists("tag", country.tag!!)) {
+ if (countryRepository.exists("tag", country.tag)) {
call.respond(HttpStatusCode.Conflict, "$entityName already exists")
return@post
}
- if (isExists("name", country.name!!)) {
+ if (countryRepository.exists("name", country.name)) {
call.respond(HttpStatusCode.Conflict, "$entityName already exists")
return@post
}
- call.respond(HttpStatusCode.Created, justSave(country))
+ call.respond(HttpStatusCode.Created, countryRepository.save(country))
} catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
+ printError(call, e)
}
}
}
diff --git a/src/main/kotlin/fr/ziedelth/controllers/DeviceController.kt b/src/main/kotlin/fr/ziedelth/controllers/DeviceController.kt
deleted file mode 100644
index 37ccd69..0000000
--- a/src/main/kotlin/fr/ziedelth/controllers/DeviceController.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-package fr.ziedelth.controllers
-
-import com.google.gson.Gson
-import com.google.gson.JsonObject
-import fr.ziedelth.entities.Device
-import fr.ziedelth.entities.isNullOrNotValid
-import io.ktor.http.*
-import io.ktor.server.application.*
-import io.ktor.server.request.*
-import io.ktor.server.response.*
-import io.ktor.server.routing.*
-import java.util.*
-
-object DeviceController : IController("/devices") {
- private fun update(device: Device) {
- val newDevice = getBy("name", device.name)
-
- if (newDevice.isNullOrNotValid()) {
- println("Missing parameters")
- println(device)
- return
- }
-
- newDevice!!.os = device.os
- newDevice.model = device.model
- newDevice.updatedAt = Calendar.getInstance()
- justUpdate(newDevice)
- }
-
- fun update(name: String, device: Device? = null) {
- val newDevice = device ?: getBy("name", name) ?: return
- newDevice.updatedAt = Calendar.getInstance()
- justUpdate(newDevice)
- }
-
- fun Routing.getDevices() {
- route(prefix) {
- create()
- }
- }
-
- private fun Route.create() {
- post {
- try {
- val gson = Gson().fromJson(call.receiveText(), JsonObject::class.java)
-
- val device = Device(
- name = gson.get("name")?.asString,
- os = gson.get("os")?.asString,
- model = gson.get("model")?.asString
- )
-
- println("POST $prefix")
-
- if (device.isNullOrNotValid()) {
- println("Missing parameters")
- println(device)
- call.respond(HttpStatusCode.BadRequest, "Missing parameters")
- return@post
- }
-
- if (isExists("name", device.name)) {
- println("$entityName already exists, updating")
-
- try {
- update(device)
- call.respond(HttpStatusCode.OK, "$entityName updated")
- } catch (e: Exception) {
- println("Error while updating $entityName")
- println(e)
- call.respond(HttpStatusCode.InternalServerError, "Error while updating $entityName")
- }
-
- return@post
- }
-
- val savedDevice = justSave(device)
- call.respond(HttpStatusCode.Created, savedDevice)
- } catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- }
- }
- }
-}
diff --git a/src/main/kotlin/fr/ziedelth/controllers/DeviceRedirectionController.kt b/src/main/kotlin/fr/ziedelth/controllers/DeviceRedirectionController.kt
deleted file mode 100644
index 802076d..0000000
--- a/src/main/kotlin/fr/ziedelth/controllers/DeviceRedirectionController.kt
+++ /dev/null
@@ -1,136 +0,0 @@
-package fr.ziedelth.controllers
-
-import fr.ziedelth.entities.Device
-import fr.ziedelth.entities.Episode
-import fr.ziedelth.entities.Manga
-import fr.ziedelth.entities.device_redirections.DeviceEpisodeRedirection
-import fr.ziedelth.entities.device_redirections.DeviceMangaRedirection
-import fr.ziedelth.utils.Database
-import io.ktor.http.*
-import io.ktor.server.application.*
-import io.ktor.server.request.*
-import io.ktor.server.response.*
-import io.ktor.server.routing.*
-import java.util.*
-
-object DeviceRedirectionController : IController("/devices/redirection") {
- fun Route.getRedirection() {
- route(prefix) {
- episode()
- manga()
- }
- }
-
- private fun getEpisodeRedirection(device: Device, episode: Episode): DeviceEpisodeRedirection? {
- val session = Database.getSession()
-
- try {
- val query = session.createQuery(
- "FROM DeviceEpisodeRedirection WHERE device = :device AND episode = :episode",
- DeviceEpisodeRedirection::class.java
- )
- query.maxResults = 1
- query.setParameter("device", device)
- query.setParameter("episode", episode)
- return query.uniqueResult()
- } catch (e: Exception) {
- return null
- } finally {
- session.close()
- }
- }
-
- private fun Route.episode() {
- post("/episode") {
- try {
- val deviceName = call.request.header("Device") ?: return@post call.respond(HttpStatusCode.BadRequest)
- val episodeId = UUID.fromString(
- call.request.header("Episode") ?: return@post call.respond(
- HttpStatusCode.BadRequest
- )
- )
- println("POST $prefix/episode")
- val device = DeviceController.getBy("name", deviceName)
- val episode = EpisodeController.getBy("id", episodeId)
-
- if (device == null || episode == null) {
- println("Missing parameters")
- return@post call.respond(HttpStatusCode.BadRequest)
- }
-
- DeviceController.update(deviceName, device)
-
- val redirection = getEpisodeRedirection(device, episode)
-
- if (redirection != null) {
- redirection.timestamp = Calendar.getInstance()
- justUpdate(redirection)
- } else {
- justSave(DeviceEpisodeRedirection(device = device, episode = episode))
- }
-
- call.respond(HttpStatusCode.Created, "$entityName created")
- } catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- }
- }
- }
-
- private fun getMangaRedirection(device: Device, manga: Manga): DeviceMangaRedirection? {
- val session = Database.getSession()
-
- try {
- val query = session.createQuery(
- "FROM DeviceMangaRedirection WHERE device = :device AND manga = :manga",
- DeviceMangaRedirection::class.java
- )
- query.maxResults = 1
- query.setParameter("device", device)
- query.setParameter("manga", manga)
- return query.uniqueResult()
- } catch (e: Exception) {
- return null
- } finally {
- session.close()
- }
- }
-
- private fun Route.manga() {
- post("/manga") {
- try {
- val deviceName = call.request.header("Device") ?: return@post call.respond(HttpStatusCode.BadRequest)
- val mangaId = UUID.fromString(
- call.request.header("Manga") ?: return@post call.respond(
- HttpStatusCode.BadRequest
- )
- )
- println("POST $prefix/manga")
- val device = DeviceController.getBy("name", deviceName)
- val manga = MangaController.getBy("uuid", mangaId)
-
- if (device == null || manga == null) {
- println("Missing parameters")
- call.respond(HttpStatusCode.BadRequest)
- return@post
- }
-
- DeviceController.update(deviceName, device)
-
- val redirection = getMangaRedirection(device, manga)
-
- if (redirection != null) {
- redirection.timestamp = Calendar.getInstance()
- justUpdate(redirection)
- } else {
- justSave(DeviceMangaRedirection(device = device, manga = manga))
- }
-
- call.respond(HttpStatusCode.Created, "$entityName created")
- } catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/fr/ziedelth/controllers/DiaryController.kt b/src/main/kotlin/fr/ziedelth/controllers/DiaryController.kt
deleted file mode 100644
index 5d743b9..0000000
--- a/src/main/kotlin/fr/ziedelth/controllers/DiaryController.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-package fr.ziedelth.controllers
-
-import fr.ziedelth.entities.Anime
-import fr.ziedelth.utils.Database
-import io.ktor.http.*
-import io.ktor.server.application.*
-import io.ktor.server.response.*
-import io.ktor.server.routing.*
-
-object DiaryController : IController("/diary") {
- fun Routing.getDiary() {
- route(prefix) {
- get("/country/{country}/day/{day}") {
- val country = call.parameters["country"] ?: return@get call.respond(HttpStatusCode.BadRequest)
- val day = call.parameters["day"]?.toIntOrNull() ?: return@get call.respond(HttpStatusCode.BadRequest)
- println("GET $prefix/country/$country/day/$day")
- val session = Database.getSession()
-
- try {
- val query = session.createQuery(
- "SELECT anime FROM Episode episode WHERE episode.anime.country.tag = :tag AND current_date - to_date(episode.releaseDate, 'YYYY-MM-DDTHH:MI:SS') <= 7 AND FUNCTION('date_part', 'dow', to_date(episode.releaseDate, 'YYYY-MM-DDTHH:MI:SS')) = :day ORDER BY episode.anime.name ASC",
- entityClass
- )
- query.setParameter("tag", country)
- query.setParameter("day", day)
- val list = query.list()?.distinctBy { it.uuid }
- call.respond(list ?: HttpStatusCode.NotFound)
- } catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- } finally {
- session.close()
- }
- }
- }
- }
-}
diff --git a/src/main/kotlin/fr/ziedelth/controllers/EpisodeController.kt b/src/main/kotlin/fr/ziedelth/controllers/EpisodeController.kt
index fc43eb7..50fde26 100644
--- a/src/main/kotlin/fr/ziedelth/controllers/EpisodeController.kt
+++ b/src/main/kotlin/fr/ziedelth/controllers/EpisodeController.kt
@@ -1,140 +1,42 @@
package fr.ziedelth.controllers
-import com.google.gson.Gson
import fr.ziedelth.entities.Episode
import fr.ziedelth.entities.Simulcast
import fr.ziedelth.entities.isNullOrNotValid
import fr.ziedelth.events.EpisodesReleaseEvent
-import fr.ziedelth.utils.Database
-import fr.ziedelth.utils.Decoder
+import fr.ziedelth.repositories.*
import fr.ziedelth.utils.ImageCache
-import fr.ziedelth.utils.RequestCache
import fr.ziedelth.utils.plugins.PluginManager
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
-import java.util.*
-object EpisodeController : IController("/episodes") {
- fun Routing.getEpisodes() {
- route(prefix) {
- getWithPage()
- getAnimeWithPage()
- getWatchlistWithPage()
+class EpisodeController(
+ private val platformRepository: PlatformRepository,
+ private val animeRepository: AnimeRepository,
+ private val simulcastRepository: SimulcastRepository,
+ private val episodeTypeRepository: EpisodeTypeRepository,
+ private val langTypeRepository: LangTypeRepository,
+ private val episodeRepository: EpisodeRepository,
+) : IController("/episodes") {
+ fun getRoutes(routing: Routing) {
+ routing.route(prefix) {
+ getWithPage(episodeRepository)
+ getAnimeWithPage(episodeRepository)
+ getWatchlistWithPage(episodeRepository)
getAttachment()
create()
}
}
- private fun Route.getWithPage() {
- get("/country/{country}/page/{page}/limit/{limit}") {
- val country = call.parameters["country"] ?: return@get call.respond(HttpStatusCode.BadRequest)
- val page = call.parameters["page"]?.toInt() ?: return@get call.respond(HttpStatusCode.BadRequest)
- val limit = call.parameters["limit"]?.toInt() ?: return@get call.respond(HttpStatusCode.BadRequest)
- if (page < 1 || limit < 1) return@get call.respond(HttpStatusCode.BadRequest)
- if (limit > 30) return@get call.respond(HttpStatusCode.BadRequest)
- println("GET $prefix/country/$country/page/$page/limit/$limit")
- val request = RequestCache.get(uuidRequest, country, page, limit)
-
- if (request == null || request.isExpired()) {
- val session = Database.getSession()
-
- try {
- val query = session.createQuery(
- "FROM Episode WHERE anime.country.tag = :tag ORDER BY releaseDate DESC, anime.name, season DESC, number DESC, episodeType.name, langType.name",
- Episode::class.java
- )
- query.setParameter("tag", country)
- query.firstResult = (limit * page) - limit
- query.maxResults = limit
- request?.update(query.list()) ?: RequestCache.put(
- uuidRequest,
- country,
- page,
- limit,
- value = query.list()
- )
- } catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- } finally {
- session.close()
- }
- }
-
- call.respond(RequestCache.get(uuidRequest, country, page, limit)?.value ?: HttpStatusCode.NotFound)
- }
- }
-
- private fun Route.getAnimeWithPage() {
- get("/anime/{uuid}/page/{page}/limit/{limit}") {
- val animeUuid = call.parameters["uuid"] ?: return@get call.respond(HttpStatusCode.BadRequest)
- val page = call.parameters["page"]?.toInt() ?: return@get call.respond(HttpStatusCode.BadRequest)
- val limit = call.parameters["limit"]?.toInt() ?: return@get call.respond(HttpStatusCode.BadRequest)
- if (page < 1 || limit < 1) return@get call.respond(HttpStatusCode.BadRequest)
- if (limit > 30) return@get call.respond(HttpStatusCode.BadRequest)
- println("GET $prefix/anime/$animeUuid/page/$page/limit/$limit")
- val session = Database.getSession()
-
- try {
- val query = session.createQuery(
- "FROM Episode WHERE anime.uuid = :uuid ORDER BY season DESC, number DESC, episodeType.name, langType.name",
- Episode::class.java
- )
- query.setParameter("uuid", UUID.fromString(animeUuid))
- query.firstResult = (limit * page) - limit
- query.maxResults = limit
- call.respond(query.list() ?: HttpStatusCode.NotFound)
- } catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- } finally {
- session.close()
- }
- }
- }
-
- private fun Route.getWatchlistWithPage() {
- post("/watchlist/page/{page}/limit/{limit}") {
- val watchlist = call.receive()
- val page = call.parameters["page"]?.toInt() ?: return@post call.respond(HttpStatusCode.BadRequest)
- val limit = call.parameters["limit"]?.toInt() ?: return@post call.respond(HttpStatusCode.BadRequest)
- if (page < 1 || limit < 1) return@post call.respond(HttpStatusCode.BadRequest)
- if (limit > 30) return@post call.respond(HttpStatusCode.BadRequest)
- println("POST $prefix/watchlist/page/$page/limit/$limit")
- val session = Database.getSession()
-
- try {
- val dataFromGzip =
- Gson().fromJson(Decoder.fromGzip(watchlist), Array::class.java).map { UUID.fromString(it) }
-
- val query = session.createQuery(
- "FROM $entityName WHERE anime.uuid IN :list ORDER BY releaseDate DESC, anime.name, season DESC, number DESC, episodeType.name, langType.name",
- entityClass
- )
- query.setParameter("list", dataFromGzip)
- query.firstResult = (limit * page) - limit
- query.maxResults = limit
- call.respond(query.list())
- } catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- } finally {
- session.close()
- }
- }
- }
-
private fun merge(episode: Episode) {
- episode.platform =
- PlatformController.getBy("uuid", episode.platform!!.uuid) ?: throw Exception("Platform not found")
- episode.anime = AnimeController.getBy("uuid", episode.anime!!.uuid) ?: throw Exception("Anime not found")
+ episode.platform = platformRepository.find(episode.platform!!.uuid) ?: throw Exception("Platform not found")
+ episode.anime = animeRepository.find(episode.anime!!.uuid) ?: throw Exception("Anime not found")
episode.episodeType =
- EpisodeTypeController.getBy("uuid", episode.episodeType!!.uuid) ?: throw Exception("EpisodeType not found")
- episode.langType =
- LangTypeController.getBy("uuid", episode.langType!!.uuid) ?: throw Exception("LangType not found")
+ episodeTypeRepository.find(episode.episodeType!!.uuid) ?: throw Exception("EpisodeType not found")
+ episode.langType = langTypeRepository.find(episode.langType!!.uuid) ?: throw Exception("LangType not found")
if (episode.isNullOrNotValid()) {
throw Exception("Episode is not valid")
@@ -142,7 +44,8 @@ object EpisodeController : IController("/episodes") {
val tmpSimulcast =
Simulcast.getSimulcast(episode.releaseDate.split("-")[0].toInt(), episode.releaseDate.split("-")[1].toInt())
- val simulcast = SimulcastController.getBy(tmpSimulcast)
+ val simulcast =
+ simulcastRepository.findBySeasonAndYear(tmpSimulcast.season!!, tmpSimulcast.year!!) ?: tmpSimulcast
if (episode.anime!!.simulcasts.isEmpty() || episode.anime!!.simulcasts.none { it.uuid == simulcast.uuid }) {
episode.anime!!.simulcasts.add(simulcast)
@@ -154,21 +57,20 @@ object EpisodeController : IController("/episodes") {
println("POST $prefix/multiple")
try {
- val episodes = call.receive>().filter { !isExists("hash", it.hash!!) }
+ val episodes = call.receive>().filter { !episodeRepository.exists("hash", it.hash!!) }
val savedEpisodes = mutableListOf()
episodes.forEach {
merge(it)
- val savedEpisode = justSave(it)
+ val savedEpisode = episodeRepository.save(it)
savedEpisodes.add(savedEpisode)
ImageCache.cachingNetworkImage(savedEpisode.uuid, savedEpisode.image!!)
}
- call.respond(HttpStatusCode.Created, episodes)
+ call.respond(HttpStatusCode.Created, savedEpisodes)
PluginManager.callEvent(EpisodesReleaseEvent(savedEpisodes))
} catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
+ printError(call, e)
}
}
}
diff --git a/src/main/kotlin/fr/ziedelth/controllers/EpisodeTypeController.kt b/src/main/kotlin/fr/ziedelth/controllers/EpisodeTypeController.kt
index 8685b2a..a264eac 100644
--- a/src/main/kotlin/fr/ziedelth/controllers/EpisodeTypeController.kt
+++ b/src/main/kotlin/fr/ziedelth/controllers/EpisodeTypeController.kt
@@ -1,20 +1,30 @@
package fr.ziedelth.controllers
import fr.ziedelth.entities.EpisodeType
+import fr.ziedelth.entities.isNullOrNotValid
+import fr.ziedelth.repositories.EpisodeTypeRepository
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
-object EpisodeTypeController : IController("/episodetypes") {
- fun Routing.getEpisodeTypes() {
- route(prefix) {
+class EpisodeTypeController(private val episodeTypeRepository: EpisodeTypeRepository) :
+ IController("/episodetypes") {
+ fun getRoutes(routing: Routing) {
+ routing.route(prefix) {
getAll()
create()
}
}
+ fun Route.getAll() {
+ get {
+ println("GET $prefix")
+ call.respond(episodeTypeRepository.getAll())
+ }
+ }
+
private fun Route.create() {
post {
println("POST $prefix")
@@ -22,20 +32,19 @@ object EpisodeTypeController : IController("/episodetypes") {
try {
val episodeType = call.receive()
- if (episodeType.name.isNullOrBlank()) {
- call.respond(HttpStatusCode.BadRequest, "Missing parameters")
+ if (episodeType.isNullOrNotValid()) {
+ call.respond(HttpStatusCode.BadRequest, MISSING_PARAMETERS_MESSAGE_ERROR)
return@post
}
- if (isExists("name", episodeType.name)) {
+ if (episodeTypeRepository.exists("name", episodeType.name)) {
call.respond(HttpStatusCode.Conflict, "$entityName already exists")
return@post
}
- call.respond(HttpStatusCode.Created, justSave(episodeType))
+ call.respond(HttpStatusCode.Created, episodeTypeRepository.save(episodeType))
} catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
+ printError(call, e)
}
}
}
diff --git a/src/main/kotlin/fr/ziedelth/controllers/GenreController.kt b/src/main/kotlin/fr/ziedelth/controllers/GenreController.kt
index f148bd2..24cfcb4 100644
--- a/src/main/kotlin/fr/ziedelth/controllers/GenreController.kt
+++ b/src/main/kotlin/fr/ziedelth/controllers/GenreController.kt
@@ -1,20 +1,29 @@
package fr.ziedelth.controllers
import fr.ziedelth.entities.Genre
+import fr.ziedelth.entities.isNullOrNotValid
+import fr.ziedelth.repositories.GenreRepository
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
-object GenreController : IController("/genres") {
- fun Routing.getGenres() {
- route(prefix) {
+class GenreController(private val genreRepository: GenreRepository) : IController("/genres") {
+ fun getRoutes(routing: Routing) {
+ routing.route(prefix) {
getAll()
create()
}
}
+ fun Route.getAll() {
+ get {
+ println("GET $prefix")
+ call.respond(genreRepository.getAll())
+ }
+ }
+
private fun Route.create() {
post {
println("POST $prefix")
@@ -22,20 +31,19 @@ object GenreController : IController("/genres") {
try {
val genre = call.receive()
- if (genre.name.isNullOrBlank()) {
- call.respond(HttpStatusCode.BadRequest, "Missing parameters")
+ if (genre.isNullOrNotValid()) {
+ call.respond(HttpStatusCode.BadRequest, MISSING_PARAMETERS_MESSAGE_ERROR)
return@post
}
- if (isExists("name", genre.name)) {
+ if (genreRepository.exists("name", genre.name)) {
call.respond(HttpStatusCode.Conflict, "$entityName already exists")
return@post
}
- call.respond(HttpStatusCode.Created, justSave(genre))
+ call.respond(HttpStatusCode.Created, genreRepository.save(genre))
} catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
+ printError(call, e)
}
}
}
diff --git a/src/main/kotlin/fr/ziedelth/controllers/IController.kt b/src/main/kotlin/fr/ziedelth/controllers/IController.kt
deleted file mode 100644
index 4b15407..0000000
--- a/src/main/kotlin/fr/ziedelth/controllers/IController.kt
+++ /dev/null
@@ -1,170 +0,0 @@
-package fr.ziedelth.controllers
-
-import fr.ziedelth.utils.Database
-import fr.ziedelth.utils.ImageCache
-import io.ktor.http.*
-import io.ktor.server.application.*
-import io.ktor.server.response.*
-import io.ktor.server.routing.*
-import java.io.Serializable
-import java.lang.reflect.ParameterizedType
-import java.util.*
-
-open class IController(val prefix: String) {
- val entityClass: Class =
- (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class
- val entityName: String = entityClass.simpleName
- val uuidRequest: UUID = UUID.randomUUID()
-
- private fun getAll(): MutableList {
- val session = Database.getSession()
-
- try {
- val query = session.createQuery("FROM $entityName", entityClass)
- return query.list()
- } catch (e: Exception) {
- e.printStackTrace()
- println("Error while getting $prefix : ${e.message}")
- throw e
- } finally {
- session.close()
- }
- }
-
- fun getAllBy(field: String, value: Any?): MutableList {
- val session = Database.getSession()
-
- try {
- val query = session.createQuery(
- "FROM $entityName WHERE $field = :${field.filter { it.isLetterOrDigit() }.trim()}",
- entityClass
- )
- query.setParameter(field.filter { it.isLetterOrDigit() }.trim(), value)
- return query.list()
- } catch (e: Exception) {
- e.printStackTrace()
- println("Error while getting $prefix : ${e.message}")
- throw e
- } finally {
- session.close()
- }
- }
-
- fun getBy(field: String, value: Any?): T? {
- val session = Database.getSession()
-
- try {
- val query = session.createQuery("FROM $entityName WHERE $field = :$field", entityClass)
- query.maxResults = 1
- query.setParameter(field, value)
- return query.uniqueResult()
- } catch (e: Exception) {
- e.printStackTrace()
- println("Error while getting $prefix : ${e.message}")
- throw e
- } finally {
- session.close()
- }
- }
-
- fun isExists(field: String, value: Any?): Boolean {
- val session = Database.getSession()
- val query = session.createQuery("SELECT COUNT(*) FROM $entityName WHERE $field = :$field", Long::class.java)
- query.maxResults = 1
- query.setParameter(field, value)
- val list = query.uniqueResult()
- session.close()
- return list > 0
- }
-
- fun contains(fieldList: String, searchValue: String?): Boolean {
- val session = Database.getSession()
- val query = session.createQuery(
- "SELECT COUNT(*) FROM $entityName JOIN $fieldList l WHERE l = :search",
- Long::class.java
- )
- query.maxResults = 1
- query.setParameter("search", searchValue)
- val list = query.uniqueResult()
- session.close()
- return list > 0
- }
-
- fun justSave(dtoIn: T): T {
- val session = Database.getSession()
- val transaction = session.beginTransaction()
-
- try {
- val entity = session.merge(dtoIn)
- session.persist(entity)
- transaction.commit()
- return entity
- } catch (e: Exception) {
- e.printStackTrace()
- println("Error while saving $prefix : ${e.message}")
- transaction.rollback()
- throw e
- } finally {
- session.close()
- }
- }
-
- fun justUpdate(dtoIn: T) {
- val session = Database.getSession()
- val transaction = session.beginTransaction()
-
- try {
- session.update(dtoIn)
- transaction.commit()
- } catch (e: Exception) {
- e.printStackTrace()
- println("Error while updating $prefix : ${e.message}")
- transaction.rollback()
- throw e
- } finally {
- session.close()
- }
- }
-
- fun Route.getAll() {
- get {
- println("GET $prefix")
-
- try {
- call.respond(this@IController.getAll())
- } catch (e: Exception) {
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- }
- }
- }
-
- fun Route.getAttachment() {
- get("/attachment/{uuid}") {
- val string = call.parameters["uuid"] ?: return@get call.respond(HttpStatusCode.BadRequest)
- val uuidRegex =
- "^[0-9(a-f|A-F)]{8}-[0-9(a-f|A-F)]{4}-4[0-9(a-f|A-F)]{3}-[89ab][0-9(a-f|A-F)]{3}-[0-9(a-f|A-F)]{12}\$".toRegex()
-
- if (!uuidRegex.matches(string)) {
- println("GET $prefix/attachment/$string : Invalid UUID")
- return@get call.respond(HttpStatusCode.BadRequest)
- }
-
- val uuid = UUID.fromString(string)
- println("GET ${prefix}/attachment/$uuid")
-
- if (!ImageCache.contains(uuid)) {
- println("Attachment $uuid not found")
- call.respond(HttpStatusCode.NoContent)
- return@get
- }
-
- val image = ImageCache.get(uuid) ?: run {
- println("Attachment $uuid not found")
- return@get call.respond(HttpStatusCode.NoContent)
- }
-
- println("Attachment $uuid found (${image.bytes.size} bytes)")
- call.respondBytes(image.bytes, ContentType("image", "webp"))
- }
- }
-}
diff --git a/src/main/kotlin/fr/ziedelth/controllers/LangTypeController.kt b/src/main/kotlin/fr/ziedelth/controllers/LangTypeController.kt
index aef913c..42822e3 100644
--- a/src/main/kotlin/fr/ziedelth/controllers/LangTypeController.kt
+++ b/src/main/kotlin/fr/ziedelth/controllers/LangTypeController.kt
@@ -1,20 +1,29 @@
package fr.ziedelth.controllers
import fr.ziedelth.entities.LangType
+import fr.ziedelth.entities.isNullOrNotValid
+import fr.ziedelth.repositories.LangTypeRepository
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
-object LangTypeController : IController("/langtypes") {
- fun Routing.getLangTypes() {
- route(prefix) {
+class LangTypeController(private val langTypeRepository: LangTypeRepository) : IController("/langtypes") {
+ fun getRoutes(routing: Routing) {
+ routing.route(prefix) {
getAll()
create()
}
}
+ fun Route.getAll() {
+ get {
+ println("GET $prefix")
+ call.respond(langTypeRepository.getAll())
+ }
+ }
+
private fun Route.create() {
post {
println("POST $prefix")
@@ -22,20 +31,19 @@ object LangTypeController : IController("/langtypes") {
try {
val langType = call.receive()
- if (langType.name.isNullOrBlank()) {
- call.respond(HttpStatusCode.BadRequest, "Missing parameters")
+ if (langType.isNullOrNotValid()) {
+ call.respond(HttpStatusCode.BadRequest, MISSING_PARAMETERS_MESSAGE_ERROR)
return@post
}
- if (isExists("name", langType.name)) {
+ if (langTypeRepository.exists("name", langType.name)) {
call.respond(HttpStatusCode.Conflict, "$entityName already exists")
return@post
}
- call.respond(HttpStatusCode.Created, justSave(langType))
+ call.respond(HttpStatusCode.Created, langTypeRepository.save(langType))
} catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
+ printError(call, e)
}
}
}
diff --git a/src/main/kotlin/fr/ziedelth/controllers/MangaController.kt b/src/main/kotlin/fr/ziedelth/controllers/MangaController.kt
index 8870e4f..5b0d7e2 100644
--- a/src/main/kotlin/fr/ziedelth/controllers/MangaController.kt
+++ b/src/main/kotlin/fr/ziedelth/controllers/MangaController.kt
@@ -1,164 +1,52 @@
package fr.ziedelth.controllers
-import com.google.gson.Gson
import fr.ziedelth.entities.Manga
import fr.ziedelth.entities.isNullOrNotValid
import fr.ziedelth.events.MangasReleaseEvent
-import fr.ziedelth.utils.Database
-import fr.ziedelth.utils.Decoder
+import fr.ziedelth.repositories.AnimeRepository
+import fr.ziedelth.repositories.MangaRepository
+import fr.ziedelth.repositories.PlatformRepository
import fr.ziedelth.utils.ImageCache
-import fr.ziedelth.utils.RequestCache
import fr.ziedelth.utils.plugins.PluginManager
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
-import java.util.*
-object MangaController : IController("/mangas") {
- fun Routing.getMangas() {
- route(prefix) {
+class MangaController(
+ private val platformRepository: PlatformRepository,
+ private val animeRepository: AnimeRepository,
+ private val mangaRepository: MangaRepository,
+) : IController("/mangas") {
+ fun getRoutes(routing: Routing) {
+ routing.route(prefix) {
search()
- getWithPage()
- getAnimeWithPage()
- getWatchlistWithPage()
+ getWithPage(mangaRepository)
+ getAnimeWithPage(mangaRepository)
+ getWatchlistWithPage(mangaRepository)
getAttachment()
create()
}
}
private fun Route.search() {
- route("/country/{country}/search") {
- get("/ean/{ean}") {
- val country = call.parameters["country"] ?: return@get call.respond(HttpStatusCode.BadRequest)
- val ean = call.parameters["ean"]?.toLongOrNull() ?: return@get call.respond(HttpStatusCode.BadRequest)
- println("GET ${prefix}/country/$country/search/ean/$ean")
- val session = Database.getSession()
-
- try {
- val query = session.createQuery(
- "FROM $entityName WHERE anime.country.tag = :tag AND ean = :ean",
- entityClass
- )
- query.maxResults = 1
- query.setParameter("tag", country)
- query.setParameter("ean", ean)
- call.respond(query.uniqueResult() ?: return@get call.respond(HttpStatusCode.NotFound))
- } catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- } finally {
- session.close()
- }
- }
- }
- }
-
- private fun Route.getWithPage() {
- get("/country/{country}/page/{page}/limit/{limit}") {
- val country = call.parameters["country"] ?: return@get call.respond(HttpStatusCode.BadRequest)
- val page = call.parameters["page"]?.toInt() ?: return@get call.respond(HttpStatusCode.BadRequest)
- val limit = call.parameters["limit"]?.toInt() ?: return@get call.respond(HttpStatusCode.BadRequest)
- if (page < 1 || limit < 1) return@get call.respond(HttpStatusCode.BadRequest)
- if (limit > 30) return@get call.respond(HttpStatusCode.BadRequest)
- println("GET $prefix/country/$country/page/$page/limit/$limit")
- val request = RequestCache.get(uuidRequest, country, page, limit)
-
- if (request == null || request.isExpired()) {
- val session = Database.getSession()
-
- try {
- val query = session.createQuery(
- "FROM $entityName WHERE anime.country.tag = :tag AND ean IS NOT NULL ORDER BY releaseDate DESC, anime.name",
- entityClass
- )
- query.setParameter("tag", country)
- query.firstResult = (limit * page) - limit
- query.maxResults = limit
- request?.update(query.list()) ?: RequestCache.put(
- uuidRequest,
- country,
- page,
- limit,
- value = query.list()
- )
- } catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- } finally {
- session.close()
- }
- }
-
- call.respond(RequestCache.get(uuidRequest, country, page, limit)?.value ?: HttpStatusCode.NotFound)
- }
- }
-
- private fun Route.getAnimeWithPage() {
- get("/anime/{uuid}/page/{page}/limit/{limit}") {
- val animeUuid = call.parameters["uuid"] ?: return@get call.respond(HttpStatusCode.BadRequest)
- val page = call.parameters["page"]?.toInt() ?: return@get call.respond(HttpStatusCode.BadRequest)
- val limit = call.parameters["limit"]?.toInt() ?: return@get call.respond(HttpStatusCode.BadRequest)
- if (page < 1 || limit < 1) return@get call.respond(HttpStatusCode.BadRequest)
- if (limit > 30) return@get call.respond(HttpStatusCode.BadRequest)
- println("GET ${prefix}/anime/$animeUuid/page/$page/limit/$limit")
- val session = Database.getSession()
-
+ get("/country/{country}/search/ean/{ean}") {
try {
- val query = session.createQuery(
- "FROM $entityName WHERE anime.uuid = :uuid ORDER BY releaseDate DESC, anime.name",
- entityClass
- )
- query.setParameter("uuid", UUID.fromString(animeUuid))
- query.firstResult = (limit * page) - limit
- query.maxResults = limit
- call.respond(query.list() ?: HttpStatusCode.NotFound)
- } catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- } finally {
- session.close()
- }
- }
- }
-
- private fun Route.getWatchlistWithPage() {
- post("/watchlist/page/{page}/limit/{limit}") {
- val watchlist = call.receive()
- val page = call.parameters["page"]?.toInt() ?: return@post call.respond(HttpStatusCode.BadRequest)
- val limit = call.parameters["limit"]?.toInt() ?: return@post call.respond(HttpStatusCode.BadRequest)
- if (page < 1 || limit < 1) return@post call.respond(HttpStatusCode.BadRequest)
- if (limit > 30) return@post call.respond(HttpStatusCode.BadRequest)
- println("POST $prefix/watchlist/page/$page/limit/$limit")
- val session = Database.getSession()
-
- try {
- val dataFromGzip =
- Gson().fromJson(Decoder.fromGzip(watchlist), Array::class.java).map { UUID.fromString(it) }
-
- val query = session.createQuery(
- "FROM $entityName WHERE uuid IN :list ORDER BY releaseDate DESC, anime.name",
- entityClass
- )
- query.setParameter("list", dataFromGzip)
- query.firstResult = (limit * page) - limit
- query.maxResults = limit
- call.respond(query.list())
+ val country = call.parameters["country"]!!
+ val ean = call.parameters["ean"]!!.toLongOrNull() ?: return@get call.respond(HttpStatusCode.BadRequest)
+ println("GET ${prefix}/country/$country/search/ean/$ean")
+ call.respond(mangaRepository.getByEAN(country, ean) ?: return@get call.respond(HttpStatusCode.NotFound))
} catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- } finally {
- session.close()
+ printError(call, e)
}
}
}
-
private fun merge(manga: Manga) {
manga.platform =
- PlatformController.getBy("uuid", manga.platform!!.uuid) ?: throw Exception("Platform not found")
- manga.anime = AnimeController.getBy("uuid", manga.anime!!.uuid) ?: throw Exception("Anime not found")
+ platformRepository.find(manga.platform!!.uuid) ?: throw Exception("Platform not found")
+ manga.anime = animeRepository.find(manga.anime!!.uuid) ?: throw Exception("Anime not found")
if (manga.isNullOrNotValid()) {
throw Exception("Manga is not valid")
@@ -170,21 +58,20 @@ object MangaController : IController("/mangas") {
println("POST $prefix/multiple")
try {
- val mangas = call.receive>().filter { !isExists("hash", it.hash!!) }
+ val mangas = call.receive>().filter { !mangaRepository.exists("hash", it.hash!!) }
val savedMangas = mutableListOf()
mangas.forEach {
merge(it)
- val savedManga = justSave(it)
+ val savedManga = mangaRepository.save(it)
savedMangas.add(savedManga)
ImageCache.cachingNetworkImage(savedManga.uuid, savedManga.cover!!)
}
- call.respond(HttpStatusCode.Created, mangas)
+ call.respond(HttpStatusCode.Created, savedMangas)
PluginManager.callEvent(MangasReleaseEvent(savedMangas))
} catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
+ printError(call, e)
}
}
}
diff --git a/src/main/kotlin/fr/ziedelth/controllers/NewsController.kt b/src/main/kotlin/fr/ziedelth/controllers/NewsController.kt
index f2861ed..9c3f9ac 100644
--- a/src/main/kotlin/fr/ziedelth/controllers/NewsController.kt
+++ b/src/main/kotlin/fr/ziedelth/controllers/NewsController.kt
@@ -3,8 +3,9 @@ package fr.ziedelth.controllers
import fr.ziedelth.entities.News
import fr.ziedelth.entities.isNullOrNotValid
import fr.ziedelth.events.NewsReleaseEvent
-import fr.ziedelth.utils.Database
-import fr.ziedelth.utils.RequestCache
+import fr.ziedelth.repositories.CountryRepository
+import fr.ziedelth.repositories.NewsRepository
+import fr.ziedelth.repositories.PlatformRepository
import fr.ziedelth.utils.plugins.PluginManager
import io.ktor.http.*
import io.ktor.server.application.*
@@ -12,57 +13,21 @@ import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
-object NewsController : IController("/news") {
- fun Routing.getNews() {
- route(prefix) {
- getWithPage()
+class NewsController(
+ private val countryRepository: CountryRepository,
+ private val platformRepository: PlatformRepository,
+ private val newsRepository: NewsRepository,
+) : IController("/news") {
+ fun getRoutes(routing: Routing) {
+ routing.route(prefix) {
+ getWithPage(newsRepository)
create()
}
}
- private fun Route.getWithPage() {
- get("/country/{country}/page/{page}/limit/{limit}") {
- val country = call.parameters["country"] ?: return@get call.respond(HttpStatusCode.BadRequest)
- val page = call.parameters["page"]?.toInt() ?: return@get call.respond(HttpStatusCode.BadRequest)
- val limit = call.parameters["limit"]?.toInt() ?: return@get call.respond(HttpStatusCode.BadRequest)
- if (page < 1 || limit < 1) return@get call.respond(HttpStatusCode.BadRequest)
- if (limit > 30) return@get call.respond(HttpStatusCode.BadRequest)
- println("GET $prefix/country/$country/page/$page/limit/$limit")
- val request = RequestCache.get(uuidRequest, country, page, limit)
-
- if (request == null || request.isExpired()) {
- val session = Database.getSession()
-
- try {
- val query = session.createQuery(
- "FROM News WHERE country.tag = :tag ORDER BY releaseDate DESC",
- News::class.java
- )
- query.setParameter("tag", country)
- query.firstResult = (limit * page) - limit
- query.maxResults = limit
- request?.update(query.list()) ?: RequestCache.put(
- uuidRequest,
- country,
- page,
- limit,
- value = query.list()
- )
- } catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- } finally {
- session.close()
- }
- }
-
- call.respond(RequestCache.get(uuidRequest, country, page, limit)?.value ?: HttpStatusCode.NotFound)
- }
- }
-
private fun merge(news: News) {
- news.platform = PlatformController.getBy("uuid", news.platform!!.uuid) ?: throw Exception("Platform not found")
- news.country = CountryController.getBy("uuid", news.country!!.uuid) ?: throw Exception("Country not found")
+ news.platform = platformRepository.find(news.platform!!.uuid) ?: throw Exception("Platform not found")
+ news.country = countryRepository.find(news.country!!.uuid) ?: throw Exception("Country not found")
if (news.isNullOrNotValid()) {
throw Exception("News is not valid")
@@ -74,19 +39,18 @@ object NewsController : IController("/news") {
println("POST $prefix/multiple")
try {
- val news = call.receive>().filter { !isExists("hash", it.hash!!) }
+ val news = call.receive>().filter { !newsRepository.exists("hash", it.hash!!) }
val savedNews = mutableListOf()
news.forEach {
merge(it)
- savedNews.add(justSave(it))
+ savedNews.add(newsRepository.save(it))
}
- call.respond(HttpStatusCode.Created, news)
+ call.respond(HttpStatusCode.Created, savedNews)
PluginManager.callEvent(NewsReleaseEvent(savedNews))
} catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
+ printError(call, e)
}
}
}
diff --git a/src/main/kotlin/fr/ziedelth/controllers/PlatformController.kt b/src/main/kotlin/fr/ziedelth/controllers/PlatformController.kt
index 75153b8..c5a51c9 100644
--- a/src/main/kotlin/fr/ziedelth/controllers/PlatformController.kt
+++ b/src/main/kotlin/fr/ziedelth/controllers/PlatformController.kt
@@ -1,21 +1,30 @@
package fr.ziedelth.controllers
import fr.ziedelth.entities.Platform
+import fr.ziedelth.entities.isNullOrNotValid
+import fr.ziedelth.repositories.PlatformRepository
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
-object PlatformController : IController("/platforms") {
- fun Routing.getPlatforms() {
- route(prefix) {
+class PlatformController(private val platformRepository: PlatformRepository) : IController("/platforms") {
+ fun getRoutes(routing: Routing) {
+ routing.route(prefix) {
getAll()
getAttachment()
create()
}
}
+ fun Route.getAll() {
+ get {
+ println("GET $prefix")
+ call.respond(platformRepository.getAll())
+ }
+ }
+
private fun Route.create() {
post {
println("POST $prefix")
@@ -23,20 +32,19 @@ object PlatformController : IController("/platforms") {
try {
val platform = call.receive()
- if (platform.name.isNullOrBlank() || platform.url.isNullOrBlank() || platform.image.isNullOrBlank()) {
- call.respond(HttpStatusCode.BadRequest, "Missing parameters")
+ if (platform.isNullOrNotValid()) {
+ call.respond(HttpStatusCode.BadRequest, MISSING_PARAMETERS_MESSAGE_ERROR)
return@post
}
- if (isExists("name", platform.name)) {
+ if (platformRepository.exists("name", platform.name)) {
call.respond(HttpStatusCode.Conflict, "$entityName already exists")
return@post
}
- call.respond(HttpStatusCode.Created, justSave(platform))
+ call.respond(HttpStatusCode.Created, platformRepository.save(platform))
} catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
+ printError(call, e)
}
}
}
diff --git a/src/main/kotlin/fr/ziedelth/controllers/SimulcastController.kt b/src/main/kotlin/fr/ziedelth/controllers/SimulcastController.kt
index 2d52625..3a71116 100644
--- a/src/main/kotlin/fr/ziedelth/controllers/SimulcastController.kt
+++ b/src/main/kotlin/fr/ziedelth/controllers/SimulcastController.kt
@@ -1,52 +1,20 @@
package fr.ziedelth.controllers
import fr.ziedelth.entities.Simulcast
-import fr.ziedelth.utils.Database
-import io.ktor.http.*
+import fr.ziedelth.repositories.SimulcastRepository
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
-object SimulcastController : IController("/simulcasts") {
- fun Routing.getSimulcasts() {
- route(prefix) {
+class SimulcastController(private val simulcastRepository: SimulcastRepository) :
+ IController("/simulcasts") {
+ fun getRoutes(routing: Routing) {
+ routing.route(prefix) {
get("/country/{country}") {
- val country = call.parameters["country"] ?: return@get call.respond(HttpStatusCode.BadRequest)
+ val country = call.parameters["country"]!!
println("GET $prefix/country/$country")
- val session = Database.getSession()
-
- try {
- val query = session.createQuery(
- "SELECT DISTINCT simulcasts FROM Anime WHERE country.tag = :tag",
- Simulcast::class.java
- )
- query.setParameter("tag", country)
- call.respond(query.list())
- } catch (e: Exception) {
- e.printStackTrace()
- call.respond(HttpStatusCode.InternalServerError, e.message ?: "Unknown error")
- } finally {
- session.close()
- }
+ call.respond(simulcastRepository.getAll(country))
}
}
}
-
- fun getBy(simulcast: Simulcast): Simulcast {
- val session = Database.getSession()
-
- try {
- val query =
- session.createQuery("FROM Simulcast WHERE season = :season AND year = :year", Simulcast::class.java)
- query.setParameter("season", simulcast.season)
- query.setParameter("year", simulcast.year)
- return query.list().firstOrNull() ?: simulcast
- } catch (e: Exception) {
- e.printStackTrace()
- println("Error while getting $prefix : ${e.message}")
- throw e
- } finally {
- session.close()
- }
- }
}
diff --git a/src/main/kotlin/fr/ziedelth/entities/Anime.kt b/src/main/kotlin/fr/ziedelth/entities/Anime.kt
index a786a39..593287d 100644
--- a/src/main/kotlin/fr/ziedelth/entities/Anime.kt
+++ b/src/main/kotlin/fr/ziedelth/entities/Anime.kt
@@ -3,7 +3,6 @@ package fr.ziedelth.entities
import fr.ziedelth.utils.DATE_FORMAT_REGEX
import fr.ziedelth.utils.toISO8601
import jakarta.persistence.*
-import org.hibernate.Hibernate
import org.hibernate.annotations.LazyCollection
import org.hibernate.annotations.LazyCollectionOption
import java.io.Serializable
@@ -12,11 +11,12 @@ import java.util.*
fun Anime?.isNullOrNotValid() = this == null || this.isNotValid()
@Entity
-data class Anime(
+@Table(name = "anime")
+class Anime(
@Id
@GeneratedValue
val uuid: UUID = UUID.randomUUID(),
- @ManyToOne(fetch = FetchType.EAGER, cascade = [CascadeType.ALL])
+ @ManyToOne(fetch = FetchType.EAGER, cascade = [CascadeType.MERGE, CascadeType.PERSIST])
@JoinColumn(
name = "country_uuid",
nullable = false,
@@ -39,7 +39,7 @@ data class Anime(
foreignKey = ForeignKey(foreignKeyDefinition = "FOREIGN KEY (anime_uuid) REFERENCES anime (uuid) ON DELETE CASCADE")
)
val hashes: MutableSet = mutableSetOf(),
- @ManyToMany(fetch = FetchType.EAGER, cascade = [CascadeType.ALL])
+ @ManyToMany(fetch = FetchType.EAGER, cascade = [CascadeType.MERGE, CascadeType.PERSIST])
@JoinTable(
name = "anime_genre",
joinColumns = [
@@ -56,7 +56,7 @@ data class Anime(
]
)
val genres: MutableSet = mutableSetOf(),
- @ManyToMany(fetch = FetchType.EAGER, cascade = [CascadeType.ALL])
+ @ManyToMany(fetch = FetchType.EAGER, cascade = [CascadeType.MERGE, CascadeType.PERSIST])
@JoinTable(
name = "anime_simulcast",
joinColumns = [
@@ -74,27 +74,12 @@ data class Anime(
)
val simulcasts: MutableSet = mutableSetOf(),
) : Serializable {
- fun hash(): String? = name?.lowercase()?.filter { it.isLetterOrDigit() || it.isWhitespace() || it == '-' }?.trim()
- ?.replace("\\s+".toRegex(), "-")?.replace("--", "-")
+ fun hash(): String = name!!.lowercase().filter { it.isLetterOrDigit() || it.isWhitespace() || it == '-' }.trim()
+ .replace("\\s+".toRegex(), "-").replace("--", "-")
fun isNotValid(): Boolean = country.isNullOrNotValid() || name.isNullOrBlank() || (
releaseDate.isBlank() || !releaseDate.matches(
DATE_FORMAT_REGEX
)
) || image.isNullOrBlank()
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || Hibernate.getClass(this) != Hibernate.getClass(other)) return false
- other as Anime
-
- return uuid != null && uuid == other.uuid
- }
-
- override fun hashCode(): Int = javaClass.hashCode()
-
- @Override
- override fun toString(): String {
- return this::class.simpleName + "(uuid = $uuid , country = $country , name = $name , releaseDate = $releaseDate , image = $image , description = $description , hashes = $hashes )"
- }
}
diff --git a/src/main/kotlin/fr/ziedelth/entities/Country.kt b/src/main/kotlin/fr/ziedelth/entities/Country.kt
index 0bea844..c66b61f 100644
--- a/src/main/kotlin/fr/ziedelth/entities/Country.kt
+++ b/src/main/kotlin/fr/ziedelth/entities/Country.kt
@@ -1,17 +1,14 @@
package fr.ziedelth.entities
-import jakarta.persistence.Column
-import jakarta.persistence.Entity
-import jakarta.persistence.GeneratedValue
-import jakarta.persistence.Id
-import org.hibernate.Hibernate
+import jakarta.persistence.*
import java.io.Serializable
import java.util.*
fun Country?.isNullOrNotValid() = this == null || this.isNotValid()
@Entity
-data class Country(
+@Table(name = "country")
+class Country(
@Id
@GeneratedValue
val uuid: UUID = UUID.randomUUID(),
@@ -21,19 +18,4 @@ data class Country(
val name: String? = null
) : Serializable {
fun isNotValid(): Boolean = tag.isNullOrBlank() || name.isNullOrBlank()
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || Hibernate.getClass(this) != Hibernate.getClass(other)) return false
- other as Country
-
- return uuid == other.uuid
- }
-
- override fun hashCode(): Int = javaClass.hashCode()
-
- @Override
- override fun toString(): String {
- return this::class.simpleName + "(uuid = $uuid , tag = $tag , name = $name )"
- }
}
diff --git a/src/main/kotlin/fr/ziedelth/entities/Device.kt b/src/main/kotlin/fr/ziedelth/entities/Device.kt
deleted file mode 100644
index 4c17bfe..0000000
--- a/src/main/kotlin/fr/ziedelth/entities/Device.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package fr.ziedelth.entities
-
-import jakarta.persistence.Column
-import jakarta.persistence.Entity
-import jakarta.persistence.GeneratedValue
-import jakarta.persistence.Id
-import org.hibernate.Hibernate
-import java.io.Serializable
-import java.util.*
-
-fun Device?.isNullOrNotValid() = this == null || this.isNotValid()
-
-@Entity
-data class Device(
- @Id
- @GeneratedValue
- val uuid: UUID = UUID.randomUUID(),
- @Column(nullable = false, unique = true)
- var name: String? = null,
- @Column(nullable = false)
- var os: String? = null,
- @Column(nullable = false)
- var model: String? = null,
- @Column(nullable = false, name = "created_at")
- val createdAt: Calendar = Calendar.getInstance(),
- @Column(nullable = false, name = "updated_at")
- var updatedAt: Calendar = Calendar.getInstance(),
-) : Serializable {
- fun isNotValid(): Boolean = name.isNullOrBlank() || os.isNullOrBlank() || model.isNullOrBlank()
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || Hibernate.getClass(this) != Hibernate.getClass(other)) return false
- other as Device
-
- return uuid != null && uuid == other.uuid
- }
-
- override fun hashCode(): Int = javaClass.hashCode()
-
- @Override
- override fun toString(): String {
- return this::class.simpleName + "(uuid = $uuid , name = $name , os = $os , model = $model , createdAt = $createdAt , updatedAt = $updatedAt )"
- }
-}
diff --git a/src/main/kotlin/fr/ziedelth/entities/Episode.kt b/src/main/kotlin/fr/ziedelth/entities/Episode.kt
index 25478ea..597ce4d 100644
--- a/src/main/kotlin/fr/ziedelth/entities/Episode.kt
+++ b/src/main/kotlin/fr/ziedelth/entities/Episode.kt
@@ -3,24 +3,18 @@ package fr.ziedelth.entities
import fr.ziedelth.utils.DATE_FORMAT_REGEX
import fr.ziedelth.utils.toISO8601
import jakarta.persistence.*
-import org.hibernate.Hibernate
import java.io.Serializable
import java.util.*
fun Episode?.isNullOrNotValid() = this == null || this.isNotValid()
@Entity
-data class Episode(
+@Table(name = "episode")
+class Episode(
@Id
@GeneratedValue
val uuid: UUID = UUID.randomUUID(),
- @ManyToOne(fetch = FetchType.EAGER, cascade = [CascadeType.ALL])
- @JoinColumn(
- name = "platform_uuid",
- nullable = false,
- foreignKey = ForeignKey(foreignKeyDefinition = "FOREIGN KEY (platform_uuid) REFERENCES platform(uuid) ON DELETE CASCADE")
- )
- var platform: Platform? = null,
+ platform: Platform? = null,
@ManyToOne(fetch = FetchType.EAGER, cascade = [CascadeType.ALL])
@JoinColumn(
name = "anime_uuid",
@@ -58,24 +52,25 @@ data class Episode(
val image: String? = null,
@Column(nullable = false)
val duration: Long = -1
-) : Serializable {
+) : Platformeable(platform), Serializable {
fun isNotValid(): Boolean =
platform.isNullOrNotValid() || anime.isNullOrNotValid() || episodeType.isNullOrNotValid() || langType.isNullOrNotValid() || hash.isNullOrBlank() || (
releaseDate.isBlank() || !releaseDate.matches(DATE_FORMAT_REGEX)
) || season == null || number == null || url.isNullOrBlank() || image.isNullOrBlank()
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || Hibernate.getClass(this) != Hibernate.getClass(other)) return false
- other as Episode
-
- return uuid == other.uuid
- }
-
- override fun hashCode(): Int = javaClass.hashCode()
-
- @Override
- override fun toString(): String {
- return this::class.simpleName + "(uuid = $uuid , platform = $platform , anime = $anime , episodeType = $episodeType , langType = $langType , hash = $hash , releaseDate = $releaseDate , season = $season , number = $number , title = $title , url = $url , image = $image , duration = $duration )"
- }
+ fun copy(anime: Anime? = this.anime) = Episode(
+ this.uuid,
+ platform,
+ anime,
+ episodeType,
+ langType,
+ hash,
+ releaseDate,
+ season,
+ number,
+ title,
+ url,
+ image,
+ duration
+ )
}
diff --git a/src/main/kotlin/fr/ziedelth/entities/EpisodeType.kt b/src/main/kotlin/fr/ziedelth/entities/EpisodeType.kt
index ef576d8..b121cc6 100644
--- a/src/main/kotlin/fr/ziedelth/entities/EpisodeType.kt
+++ b/src/main/kotlin/fr/ziedelth/entities/EpisodeType.kt
@@ -1,17 +1,14 @@
package fr.ziedelth.entities
-import jakarta.persistence.Column
-import jakarta.persistence.Entity
-import jakarta.persistence.GeneratedValue
-import jakarta.persistence.Id
-import org.hibernate.Hibernate
+import jakarta.persistence.*
import java.io.Serializable
import java.util.*
fun EpisodeType?.isNullOrNotValid() = this == null || this.isNotValid()
@Entity
-data class EpisodeType(
+@Table(name = "episodetype")
+class EpisodeType(
@Id
@GeneratedValue
val uuid: UUID = UUID.randomUUID(),
@@ -19,19 +16,4 @@ data class EpisodeType(
val name: String? = null
) : Serializable {
fun isNotValid(): Boolean = name.isNullOrBlank()
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || Hibernate.getClass(this) != Hibernate.getClass(other)) return false
- other as EpisodeType
-
- return uuid == other.uuid
- }
-
- override fun hashCode(): Int = javaClass.hashCode()
-
- @Override
- override fun toString(): String {
- return this::class.simpleName + "(uuid = $uuid , name = $name )"
- }
}
diff --git a/src/main/kotlin/fr/ziedelth/entities/Genre.kt b/src/main/kotlin/fr/ziedelth/entities/Genre.kt
index c4eb7c3..d2d1632 100644
--- a/src/main/kotlin/fr/ziedelth/entities/Genre.kt
+++ b/src/main/kotlin/fr/ziedelth/entities/Genre.kt
@@ -1,17 +1,14 @@
package fr.ziedelth.entities
-import jakarta.persistence.Column
-import jakarta.persistence.Entity
-import jakarta.persistence.GeneratedValue
-import jakarta.persistence.Id
-import org.hibernate.Hibernate
+import jakarta.persistence.*
import java.io.Serializable
import java.util.*
fun Genre?.isNullOrNotValid() = this == null || this.isNotValid()
@Entity
-data class Genre(
+@Table(name = "genre")
+class Genre(
@Id
@GeneratedValue
val uuid: UUID = UUID.randomUUID(),
@@ -19,19 +16,4 @@ data class Genre(
val name: String? = null
) : Serializable {
fun isNotValid(): Boolean = name.isNullOrBlank()
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || Hibernate.getClass(this) != Hibernate.getClass(other)) return false
- other as Genre
-
- return uuid == other.uuid
- }
-
- override fun hashCode(): Int = javaClass.hashCode()
-
- @Override
- override fun toString(): String {
- return this::class.simpleName + "(uuid = $uuid , name = $name )"
- }
}
diff --git a/src/main/kotlin/fr/ziedelth/entities/LangType.kt b/src/main/kotlin/fr/ziedelth/entities/LangType.kt
index f863feb..57f39cc 100644
--- a/src/main/kotlin/fr/ziedelth/entities/LangType.kt
+++ b/src/main/kotlin/fr/ziedelth/entities/LangType.kt
@@ -1,17 +1,14 @@
package fr.ziedelth.entities
-import jakarta.persistence.Column
-import jakarta.persistence.Entity
-import jakarta.persistence.GeneratedValue
-import jakarta.persistence.Id
-import org.hibernate.Hibernate
+import jakarta.persistence.*
import java.io.Serializable
import java.util.*
fun LangType?.isNullOrNotValid() = this == null || this.isNotValid()
@Entity
-data class LangType(
+@Table(name = "langtype")
+class LangType(
@Id
@GeneratedValue
val uuid: UUID = UUID.randomUUID(),
@@ -19,19 +16,4 @@ data class LangType(
val name: String? = null
) : Serializable {
fun isNotValid(): Boolean = name.isNullOrBlank()
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || Hibernate.getClass(this) != Hibernate.getClass(other)) return false
- other as LangType
-
- return uuid == other.uuid
- }
-
- override fun hashCode(): Int = javaClass.hashCode()
-
- @Override
- override fun toString(): String {
- return this::class.simpleName + "(uuid = $uuid , name = $name )"
- }
}
diff --git a/src/main/kotlin/fr/ziedelth/entities/Manga.kt b/src/main/kotlin/fr/ziedelth/entities/Manga.kt
index 400eba8..13b4c69 100644
--- a/src/main/kotlin/fr/ziedelth/entities/Manga.kt
+++ b/src/main/kotlin/fr/ziedelth/entities/Manga.kt
@@ -3,24 +3,18 @@ package fr.ziedelth.entities
import fr.ziedelth.utils.DATE_FORMAT_REGEX
import fr.ziedelth.utils.toISO8601
import jakarta.persistence.*
-import org.hibernate.Hibernate
import java.io.Serializable
import java.util.*
fun Manga?.isNullOrNotValid() = this == null || this.isNotValid()
@Entity
-data class Manga(
+@Table(name = "manga")
+class Manga(
@Id
@GeneratedValue
val uuid: UUID = UUID.randomUUID(),
- @ManyToOne(fetch = FetchType.EAGER, cascade = [CascadeType.ALL])
- @JoinColumn(
- name = "platform_uuid",
- nullable = false,
- foreignKey = ForeignKey(foreignKeyDefinition = "FOREIGN KEY (platform_uuid) REFERENCES platform(uuid) ON DELETE CASCADE")
- )
- var platform: Platform? = null,
+ platform: Platform? = null,
@ManyToOne(fetch = FetchType.EAGER, cascade = [CascadeType.ALL])
@JoinColumn(
name = "anime_uuid",
@@ -46,24 +40,24 @@ data class Manga(
val age: Int? = null,
@Column(nullable = true)
val price: Double? = null
-) : Serializable {
+) : Platformeable(platform), Serializable {
fun isNotValid(): Boolean =
platform.isNullOrNotValid() || anime.isNullOrNotValid() || hash.isNullOrBlank() || (releaseDate.isBlank() || !releaseDate.matches(
DATE_FORMAT_REGEX
)) || url.isNullOrBlank() || cover.isNullOrBlank() || editor.isNullOrBlank()
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || Hibernate.getClass(this) != Hibernate.getClass(other)) return false
- other as Manga
-
- return uuid != null && uuid == other.uuid
- }
-
- override fun hashCode(): Int = javaClass.hashCode()
-
- @Override
- override fun toString(): String {
- return this::class.simpleName + "(uuid = $uuid , platform = $platform , anime = $anime , hash = $hash , releaseDate = $releaseDate , url = $url , cover = $cover , editor = $editor , ref = $ref , ean = $ean , age = $age , price = $price )"
- }
+ fun copy(anime: Anime? = this.anime) = Manga(
+ uuid = uuid,
+ platform = platform,
+ anime = anime,
+ hash = hash,
+ releaseDate = releaseDate,
+ url = url,
+ cover = cover,
+ editor = editor,
+ ref = ref,
+ ean = ean,
+ age = age,
+ price = price
+ )
}
diff --git a/src/main/kotlin/fr/ziedelth/entities/News.kt b/src/main/kotlin/fr/ziedelth/entities/News.kt
index c962ca5..38763ce 100644
--- a/src/main/kotlin/fr/ziedelth/entities/News.kt
+++ b/src/main/kotlin/fr/ziedelth/entities/News.kt
@@ -3,24 +3,18 @@ package fr.ziedelth.entities
import fr.ziedelth.utils.DATE_FORMAT_REGEX
import fr.ziedelth.utils.toISO8601
import jakarta.persistence.*
-import org.hibernate.Hibernate
import java.io.Serializable
import java.util.*
fun News?.isNullOrNotValid() = this == null || this.isNotValid()
@Entity
-data class News(
+@Table(name = "news")
+class News(
@Id
@GeneratedValue
val uuid: UUID = UUID.randomUUID(),
- @ManyToOne(fetch = FetchType.EAGER, cascade = [CascadeType.ALL])
- @JoinColumn(
- name = "platform_uuid",
- nullable = false,
- foreignKey = ForeignKey(foreignKeyDefinition = "FOREIGN KEY (platform_uuid) REFERENCES platform(uuid) ON DELETE CASCADE")
- )
- var platform: Platform? = null,
+ platform: Platform? = null,
@ManyToOne(fetch = FetchType.EAGER, cascade = [CascadeType.ALL])
@JoinColumn(
name = "country_uuid",
@@ -38,24 +32,9 @@ data class News(
val description: String? = null,
@Column(nullable = false, columnDefinition = "TEXT")
val url: String? = null
-) : Serializable {
+) : Platformeable(platform), Serializable {
fun isNotValid(): Boolean =
platform.isNullOrNotValid() || country.isNullOrNotValid() || hash.isNullOrBlank() || (
releaseDate.isBlank() || !releaseDate.matches(DATE_FORMAT_REGEX)
) || title.isNullOrBlank() || description.isNullOrBlank() || url.isNullOrBlank()
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || Hibernate.getClass(this) != Hibernate.getClass(other)) return false
- other as News
-
- return uuid != null && uuid == other.uuid
- }
-
- override fun hashCode(): Int = javaClass.hashCode()
-
- @Override
- override fun toString(): String {
- return this::class.simpleName + "(uuid = $uuid , platform = $platform , country = $country , hash = $hash , releaseDate = $releaseDate , title = $title , description = $description , url = $url )"
- }
}
diff --git a/src/main/kotlin/fr/ziedelth/entities/Platform.kt b/src/main/kotlin/fr/ziedelth/entities/Platform.kt
index 8f7006b..c0cca79 100644
--- a/src/main/kotlin/fr/ziedelth/entities/Platform.kt
+++ b/src/main/kotlin/fr/ziedelth/entities/Platform.kt
@@ -1,17 +1,14 @@
package fr.ziedelth.entities
-import jakarta.persistence.Column
-import jakarta.persistence.Entity
-import jakarta.persistence.GeneratedValue
-import jakarta.persistence.Id
-import org.hibernate.Hibernate
+import jakarta.persistence.*
import java.io.Serializable
import java.util.*
fun Platform?.isNullOrNotValid() = this == null || this.isNotValid()
@Entity
-data class Platform(
+@Table(name = "platform")
+class Platform(
@Id
@GeneratedValue
val uuid: UUID = UUID.randomUUID(),
@@ -23,19 +20,4 @@ data class Platform(
val image: String? = null
) : Serializable {
fun isNotValid(): Boolean = name.isNullOrBlank() || url.isNullOrBlank() || image.isNullOrBlank()
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || Hibernate.getClass(this) != Hibernate.getClass(other)) return false
- other as Platform
-
- return uuid == other.uuid
- }
-
- override fun hashCode(): Int = javaClass.hashCode()
-
- @Override
- override fun toString(): String {
- return this::class.simpleName + "(uuid = $uuid , name = $name , url = $url , image = $image )"
- }
}
diff --git a/src/main/kotlin/fr/ziedelth/entities/Platformeable.kt b/src/main/kotlin/fr/ziedelth/entities/Platformeable.kt
new file mode 100644
index 0000000..c3e0730
--- /dev/null
+++ b/src/main/kotlin/fr/ziedelth/entities/Platformeable.kt
@@ -0,0 +1,13 @@
+package fr.ziedelth.entities
+
+import jakarta.persistence.*
+
+open class Platformeable(
+ @ManyToOne(fetch = FetchType.EAGER, cascade = [CascadeType.ALL])
+ @JoinColumn(
+ name = "platform_uuid",
+ nullable = false,
+ foreignKey = ForeignKey(foreignKeyDefinition = "FOREIGN KEY (platform_uuid) REFERENCES platform(uuid) ON DELETE CASCADE")
+ )
+ var platform: Platform? = null,
+)
\ No newline at end of file
diff --git a/src/main/kotlin/fr/ziedelth/entities/Simulcast.kt b/src/main/kotlin/fr/ziedelth/entities/Simulcast.kt
index 86304ca..5bb89d6 100644
--- a/src/main/kotlin/fr/ziedelth/entities/Simulcast.kt
+++ b/src/main/kotlin/fr/ziedelth/entities/Simulcast.kt
@@ -1,40 +1,20 @@
package fr.ziedelth.entities
import jakarta.persistence.*
-import org.hibernate.Hibernate
import java.io.Serializable
import java.util.*
-fun Simulcast?.isNullOrNotValid() = this == null || this.isNotValid()
-
@Entity
-@Table(uniqueConstraints = [UniqueConstraint(columnNames = arrayOf("season", "year"))])
-data class Simulcast(
+@Table(name = "simulcast", uniqueConstraints = [UniqueConstraint(columnNames = arrayOf("season", "year"))])
+class Simulcast(
@Id
@GeneratedValue
val uuid: UUID = UUID.randomUUID(),
@Column(nullable = false)
val season: String? = null,
- @Column(nullable = false)
+ @Column(nullable = false, name = "\"year\"")
val year: Int? = null
) : Serializable {
- fun isNotValid(): Boolean = season.isNullOrBlank() || year == null
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || Hibernate.getClass(this) != Hibernate.getClass(other)) return false
- other as Simulcast
-
- return uuid != null && uuid == other.uuid
- }
-
- override fun hashCode(): Int = javaClass.hashCode()
-
- @Override
- override fun toString(): String {
- return this::class.simpleName + "(uuid = $uuid , season = $season , year = $year )"
- }
-
companion object {
fun getSimulcast(year: Int, month: Int): Simulcast {
val seasons = arrayOf("WINTER", "SPRING", "SUMMER", "AUTUMN")
diff --git a/src/main/kotlin/fr/ziedelth/entities/device_redirections/DeviceEpisodeRedirection.kt b/src/main/kotlin/fr/ziedelth/entities/device_redirections/DeviceEpisodeRedirection.kt
deleted file mode 100644
index b743f76..0000000
--- a/src/main/kotlin/fr/ziedelth/entities/device_redirections/DeviceEpisodeRedirection.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-package fr.ziedelth.entities.device_redirections
-
-import fr.ziedelth.entities.Device
-import fr.ziedelth.entities.Episode
-import jakarta.persistence.*
-import org.hibernate.Hibernate
-import java.io.Serializable
-import java.util.*
-
-@Entity
-@Table(name = "device_episode_redirection")
-data class DeviceEpisodeRedirection(
- @Id
- @GeneratedValue
- val uuid: UUID = UUID.randomUUID(),
- @Column(nullable = false)
- var timestamp: Calendar = Calendar.getInstance(),
- @ManyToOne(optional = false)
- val device: Device? = null,
- @ManyToOne(optional = false)
- val episode: Episode? = null,
-) : Serializable {
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || Hibernate.getClass(this) != Hibernate.getClass(other)) return false
- other as DeviceEpisodeRedirection
-
- return uuid != null && uuid == other.uuid
- }
-
- override fun hashCode(): Int = javaClass.hashCode()
-
- @Override
- override fun toString(): String {
- return this::class.simpleName + "(uuid = $uuid )"
- }
-}
diff --git a/src/main/kotlin/fr/ziedelth/entities/device_redirections/DeviceMangaRedirection.kt b/src/main/kotlin/fr/ziedelth/entities/device_redirections/DeviceMangaRedirection.kt
deleted file mode 100644
index 8104ca2..0000000
--- a/src/main/kotlin/fr/ziedelth/entities/device_redirections/DeviceMangaRedirection.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-package fr.ziedelth.entities.device_redirections
-
-import fr.ziedelth.entities.Device
-import fr.ziedelth.entities.Manga
-import jakarta.persistence.*
-import org.hibernate.Hibernate
-import java.io.Serializable
-import java.util.*
-
-@Entity
-@Table(name = "device_manga_redirection")
-data class DeviceMangaRedirection(
- @Id
- @GeneratedValue
- val uuid: UUID = UUID.randomUUID(),
- @Column(nullable = false)
- var timestamp: Calendar = Calendar.getInstance(),
- @ManyToOne(optional = false)
- val device: Device? = null,
- @ManyToOne(optional = false)
- val manga: Manga? = null,
-) : Serializable {
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || Hibernate.getClass(this) != Hibernate.getClass(other)) return false
- other as DeviceMangaRedirection
-
- return uuid != null && uuid == other.uuid
- }
-
- override fun hashCode(): Int = javaClass.hashCode()
-
- @Override
- override fun toString(): String {
- return this::class.simpleName + "(uuid = $uuid , timestamp = $timestamp , device = $device , manga = $manga )"
- }
-}
diff --git a/src/main/kotlin/fr/ziedelth/plugins/HTTP.kt b/src/main/kotlin/fr/ziedelth/plugins/HTTP.kt
index 855a1f0..f38c65c 100644
--- a/src/main/kotlin/fr/ziedelth/plugins/HTTP.kt
+++ b/src/main/kotlin/fr/ziedelth/plugins/HTTP.kt
@@ -1,11 +1,11 @@
package fr.ziedelth.plugins
import io.ktor.http.*
+import io.ktor.serialization.gson.*
import io.ktor.server.application.*
import io.ktor.server.plugins.compression.*
+import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.plugins.cors.routing.*
-import io.ktor.server.websocket.*
-import java.time.Duration
fun Application.configureHTTP() {
install(Compression) {
@@ -17,16 +17,22 @@ fun Application.configureHTTP() {
minimumSize(1024) // condition
}
}
+
install(CORS) {
HttpMethod.DefaultMethods.forEach { allowMethod(it) }
allowHeader(HttpHeaders.Authorization)
anyHost()
}
- install(WebSockets) {
- pingPeriod = Duration.ofSeconds(15)
- timeout = Duration.ofSeconds(15)
- maxFrameSize = Long.MAX_VALUE
- masking = false
+ install(ContentNegotiation) {
+ gson {
+ }
}
+
+// install(WebSockets) {
+// pingPeriod = Duration.ofSeconds(15)
+// timeout = Duration.ofSeconds(15)
+// maxFrameSize = Long.MAX_VALUE
+// masking = false
+// }
}
diff --git a/src/main/kotlin/fr/ziedelth/plugins/Routing.kt b/src/main/kotlin/fr/ziedelth/plugins/Routing.kt
index 4a064e1..09e083d 100644
--- a/src/main/kotlin/fr/ziedelth/plugins/Routing.kt
+++ b/src/main/kotlin/fr/ziedelth/plugins/Routing.kt
@@ -1,42 +1,39 @@
package fr.ziedelth.plugins
-import fr.ziedelth.controllers.AnimeController.getAnimes
-import fr.ziedelth.controllers.CountryController.getCountries
-import fr.ziedelth.controllers.DeviceController.getDevices
-import fr.ziedelth.controllers.DeviceRedirectionController.getRedirection
-import fr.ziedelth.controllers.DiaryController.getDiary
-import fr.ziedelth.controllers.EpisodeController.getEpisodes
-import fr.ziedelth.controllers.EpisodeTypeController.getEpisodeTypes
-import fr.ziedelth.controllers.GenreController.getGenres
-import fr.ziedelth.controllers.LangTypeController.getLangTypes
-import fr.ziedelth.controllers.MangaController.getMangas
-import fr.ziedelth.controllers.NewsController.getNews
-import fr.ziedelth.controllers.PlatformController.getPlatforms
-import fr.ziedelth.controllers.SimulcastController.getSimulcasts
-import io.ktor.serialization.gson.*
+import fr.ziedelth.controllers.*
+import fr.ziedelth.repositories.*
import io.ktor.server.application.*
-import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.routing.*
fun Application.configureRouting() {
- install(ContentNegotiation) {
- gson {
- }
- }
-
routing {
- getCountries()
- getPlatforms()
- getSimulcasts()
- getGenres()
- getAnimes()
- getEpisodeTypes()
- getLangTypes()
- getEpisodes()
- getNews()
- getMangas()
- getDevices()
- getRedirection()
- getDiary()
+ val countryRepository = CountryRepository()
+ val platformRepository = PlatformRepository()
+ val simulcastRepository = SimulcastRepository()
+ val genreRepository = GenreRepository()
+ val animeRepository = AnimeRepository()
+ val episodeTypeRepository = EpisodeTypeRepository()
+ val langTypeRepository = LangTypeRepository()
+ val episodeRepository = EpisodeRepository()
+ val mangaRepository = MangaRepository()
+ val newsRepository = NewsRepository()
+
+ CountryController(countryRepository).getRoutes(this)
+ PlatformController(platformRepository).getRoutes(this)
+ SimulcastController(simulcastRepository).getRoutes(this)
+ GenreController(genreRepository).getRoutes(this)
+ AnimeController(countryRepository, animeRepository, episodeRepository, mangaRepository).getRoutes(this)
+ EpisodeTypeController(episodeTypeRepository).getRoutes(this)
+ LangTypeController(langTypeRepository).getRoutes(this)
+ EpisodeController(
+ platformRepository,
+ animeRepository,
+ simulcastRepository,
+ episodeTypeRepository,
+ langTypeRepository,
+ episodeRepository
+ ).getRoutes(this)
+ NewsController(countryRepository, platformRepository, newsRepository).getRoutes(this)
+ MangaController(platformRepository, animeRepository, mangaRepository).getRoutes(this)
}
}
diff --git a/src/main/kotlin/fr/ziedelth/repositories/AbstractRepository.kt b/src/main/kotlin/fr/ziedelth/repositories/AbstractRepository.kt
new file mode 100644
index 0000000..f8e86ea
--- /dev/null
+++ b/src/main/kotlin/fr/ziedelth/repositories/AbstractRepository.kt
@@ -0,0 +1,133 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.utils.Database
+import org.hibernate.Session
+import java.lang.reflect.ParameterizedType
+import java.util.*
+
+open class AbstractRepository(val getSession: () -> Session = { Database.getSession() }) {
+ private val entityClass: Class =
+ (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class
+ private val entityName: String = entityClass.simpleName
+
+ fun find(uuid: UUID): T? {
+ val session = getSession.invoke()
+ val entity = session.find(entityClass, uuid)
+ session.close()
+ return entity
+ }
+
+ fun exists(field: String, value: Any?): Boolean {
+ val session = getSession.invoke()
+ val query = session.createQuery("SELECT uuid FROM $entityName WHERE $field = :$field", UUID::class.java)
+ query.maxResults = 1
+ query.setParameter(field, value)
+ val uuid = query.uniqueResult()
+ session.close()
+ return uuid != null
+ }
+
+ fun findAll(uuids: List): List {
+ val session = getSession.invoke()
+ val entities = session.createQuery("FROM $entityName WHERE uuid IN :uuids", entityClass)
+ .setParameter("uuids", uuids)
+ .resultList
+ session.close()
+ return entities
+ }
+
+ fun getAll(): MutableList {
+ val session = getSession.invoke()
+ val list = session.createQuery("FROM $entityName", entityClass).list()
+ session.close()
+ return list
+ }
+
+ fun getAllBy(field: String, value: Any?): MutableList {
+ val session = getSession.invoke()
+ val query = session.createQuery("FROM $entityName WHERE $field = :value", entityClass)
+ query.setParameter("value", value)
+ val list = query.list()
+ session.close()
+ return list
+ }
+
+ fun save(entity: T): T {
+ val session = getSession.invoke()
+ val transaction = session.beginTransaction()
+
+ try {
+ val mergedEntity = session.merge(entity)
+ session.persist(mergedEntity)
+ transaction.commit()
+ return mergedEntity
+ } catch (e: Exception) {
+ transaction.rollback()
+ throw e
+ } finally {
+ session.close()
+ }
+ }
+
+ fun saveAll(entities: List): List {
+ val session = getSession.invoke()
+ val transaction = session.beginTransaction()
+
+ try {
+ val mergedEntities = entities.map {
+ val mergedEntity = session.merge(it)
+ session.persist(mergedEntity)
+ mergedEntity
+ }
+
+ transaction.commit()
+ return mergedEntities
+ } catch (e: Exception) {
+ transaction.rollback()
+ throw e
+ } finally {
+ session.close()
+ }
+ }
+
+ fun delete(entity: T) {
+ val session = getSession.invoke()
+ val transaction = session.beginTransaction()
+
+ try {
+ session.remove(session.merge(entity))
+ transaction.commit()
+ } catch (e: Exception) {
+ transaction.rollback()
+ throw e
+ } finally {
+ session.close()
+ }
+ }
+
+ fun deleteAll(entities: List) {
+ val session = getSession.invoke()
+ val transaction = session.beginTransaction()
+
+ try {
+ entities.forEach { session.remove(session.merge(it)) }
+ transaction.commit()
+ } catch (e: Exception) {
+ transaction.rollback()
+ throw e
+ } finally {
+ session.close()
+ }
+ }
+
+ fun getByPage(page: Int, limit: Int, queryRaw: String, vararg pair: Pair): List {
+ val session = getSession.invoke()
+ val query = session.createQuery(queryRaw, entityClass)
+ pair.forEach { query.setParameter(it.first, it.second) }
+ query.firstResult = (limit * page) - limit
+ query.maxResults = limit
+ val list = query.list()
+ session.close()
+ return list
+ }
+}
diff --git a/src/main/kotlin/fr/ziedelth/repositories/AnimeRepository.kt b/src/main/kotlin/fr/ziedelth/repositories/AnimeRepository.kt
new file mode 100644
index 0000000..72433f2
--- /dev/null
+++ b/src/main/kotlin/fr/ziedelth/repositories/AnimeRepository.kt
@@ -0,0 +1,90 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.entities.Anime
+import fr.ziedelth.utils.Database
+import org.hibernate.Session
+import java.util.*
+
+class AnimeRepository(session: () -> Session = { Database.getSession() }) : AbstractRepository(session),
+ IPageRepository {
+ fun findByHash(tag: String, hash: String): UUID? {
+ val session = getSession.invoke()
+ val query = session.createQuery(
+ "SELECT a.uuid FROM Anime a JOIN a.hashes h WHERE a.country.tag = :tag AND h = :hash",
+ UUID::class.java
+ )
+ query.maxResults = 1
+ query.setParameter("tag", tag)
+ query.setParameter("hash", hash)
+ val uuid = query.uniqueResult()
+ session.close()
+ return uuid
+ }
+
+ fun findOneByName(tag: String, name: String): Anime? {
+ val session = getSession.invoke()
+ val query = session.createQuery(
+ "FROM Anime WHERE country.tag = :tag AND LOWER(name) = :name",
+ Anime::class.java
+ )
+ query.maxResults = 1
+ query.setParameter("tag", tag)
+ query.setParameter("name", name.lowercase())
+ val uuid = query.uniqueResult()
+ session.close()
+ return uuid
+ }
+
+ fun findByName(tag: String, name: String): List {
+ val session = getSession.invoke()
+ val query = session.createQuery(
+ "SELECT DISTINCT anime FROM Episode e WHERE e.anime.country.tag = :tag AND LOWER(e.anime.name) LIKE CONCAT('%', :name, '%') ORDER BY e.anime.name",
+ Anime::class.java
+ )
+ query.setParameter("tag", tag)
+ query.setParameter("name", name.lowercase())
+ val list = query.list()
+ session.close()
+ return list
+ }
+
+ fun getByPage(tag: String, simulcast: UUID, page: Int, limit: Int): List {
+ return super.getByPage(
+ page,
+ limit,
+ "FROM Anime a JOIN a.simulcasts s WHERE a.country.tag = :tag AND s.uuid = :simulcast ORDER BY a.name",
+ "tag" to tag,
+ "simulcast" to simulcast
+ )
+ }
+
+ override fun getByPageWithList(list: List, page: Int, limit: Int): List {
+ return super.getByPage(
+ page,
+ limit,
+ "FROM Anime WHERE uuid IN :list ORDER BY name",
+ "list" to list
+ )
+ }
+
+ fun getDiary(tag: String, day: Int): List {
+ val session = getSession.invoke()
+ val query = session.createQuery(
+ "SELECT DISTINCT anime FROM Episode episode WHERE episode.anime.country.tag = :tag AND current_date - to_date(episode.releaseDate, 'YYYY-MM-DDTHH:MI:SS') <= 7 AND FUNCTION('date_part', 'dow', to_date(episode.releaseDate, 'YYYY-MM-DDTHH:MI:SS')) = :day ORDER BY episode.anime.name ASC",
+ Anime::class.java
+ )
+ query.setParameter("tag", tag)
+ query.setParameter("day", day)
+ val list = query.list()
+ session.close()
+ return list ?: emptyList()
+ }
+
+ override fun getByPage(tag: String, page: Int, limit: Int): List {
+ TODO("Not yet implemented")
+ }
+
+ override fun getByPageWithAnime(uuid: UUID, page: Int, limit: Int): List {
+ TODO("Not yet implemented")
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/fr/ziedelth/repositories/CountryRepository.kt b/src/main/kotlin/fr/ziedelth/repositories/CountryRepository.kt
new file mode 100644
index 0000000..00d9a6b
--- /dev/null
+++ b/src/main/kotlin/fr/ziedelth/repositories/CountryRepository.kt
@@ -0,0 +1,7 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.entities.Country
+import fr.ziedelth.utils.Database
+import org.hibernate.Session
+
+class CountryRepository(session: () -> Session = { Database.getSession() }) : AbstractRepository(session)
\ No newline at end of file
diff --git a/src/main/kotlin/fr/ziedelth/repositories/EpisodeRepository.kt b/src/main/kotlin/fr/ziedelth/repositories/EpisodeRepository.kt
new file mode 100644
index 0000000..8b3b61c
--- /dev/null
+++ b/src/main/kotlin/fr/ziedelth/repositories/EpisodeRepository.kt
@@ -0,0 +1,36 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.entities.Episode
+import fr.ziedelth.utils.Database
+import org.hibernate.Session
+import java.util.*
+
+class EpisodeRepository(session: () -> Session = { Database.getSession() }) : AbstractRepository(session),
+ IPageRepository {
+ override fun getByPage(tag: String, page: Int, limit: Int): List {
+ return super.getByPage(
+ page,
+ limit,
+ "FROM Episode WHERE anime.country.tag = :tag ORDER BY releaseDate DESC, anime.name, season DESC, number DESC, episodeType.name, langType.name",
+ "tag" to tag
+ )
+ }
+
+ override fun getByPageWithAnime(uuid: UUID, page: Int, limit: Int): List {
+ return super.getByPage(
+ page,
+ limit,
+ "FROM Episode WHERE anime.uuid = :uuid ORDER BY season DESC, number DESC, episodeType.name, langType.name",
+ "uuid" to uuid
+ )
+ }
+
+ override fun getByPageWithList(list: List, page: Int, limit: Int): List {
+ return super.getByPage(
+ page,
+ limit,
+ "FROM Episode WHERE anime.uuid IN :list ORDER BY releaseDate DESC, anime.name, season DESC, number DESC, episodeType.name, langType.name",
+ "list" to list
+ )
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/fr/ziedelth/repositories/EpisodeTypeRepository.kt b/src/main/kotlin/fr/ziedelth/repositories/EpisodeTypeRepository.kt
new file mode 100644
index 0000000..4c2536b
--- /dev/null
+++ b/src/main/kotlin/fr/ziedelth/repositories/EpisodeTypeRepository.kt
@@ -0,0 +1,8 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.entities.EpisodeType
+import fr.ziedelth.utils.Database
+import org.hibernate.Session
+
+class EpisodeTypeRepository(session: () -> Session = { Database.getSession() }) :
+ AbstractRepository(session)
\ No newline at end of file
diff --git a/src/main/kotlin/fr/ziedelth/repositories/GenreRepository.kt b/src/main/kotlin/fr/ziedelth/repositories/GenreRepository.kt
new file mode 100644
index 0000000..2ceddef
--- /dev/null
+++ b/src/main/kotlin/fr/ziedelth/repositories/GenreRepository.kt
@@ -0,0 +1,7 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.entities.Genre
+import fr.ziedelth.utils.Database
+import org.hibernate.Session
+
+class GenreRepository(session: () -> Session = { Database.getSession() }) : AbstractRepository(session)
\ No newline at end of file
diff --git a/src/main/kotlin/fr/ziedelth/repositories/IPageRepository.kt b/src/main/kotlin/fr/ziedelth/repositories/IPageRepository.kt
new file mode 100644
index 0000000..92b4e67
--- /dev/null
+++ b/src/main/kotlin/fr/ziedelth/repositories/IPageRepository.kt
@@ -0,0 +1,9 @@
+package fr.ziedelth.repositories
+
+import java.util.*
+
+interface IPageRepository {
+ fun getByPage(tag: String, page: Int, limit: Int): List
+ fun getByPageWithAnime(uuid: UUID, page: Int, limit: Int): List
+ fun getByPageWithList(list: List, page: Int, limit: Int): List
+}
\ No newline at end of file
diff --git a/src/main/kotlin/fr/ziedelth/repositories/LangTypeRepository.kt b/src/main/kotlin/fr/ziedelth/repositories/LangTypeRepository.kt
new file mode 100644
index 0000000..307b144
--- /dev/null
+++ b/src/main/kotlin/fr/ziedelth/repositories/LangTypeRepository.kt
@@ -0,0 +1,7 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.entities.LangType
+import fr.ziedelth.utils.Database
+import org.hibernate.Session
+
+class LangTypeRepository(session: () -> Session = { Database.getSession() }) : AbstractRepository(session)
\ No newline at end of file
diff --git a/src/main/kotlin/fr/ziedelth/repositories/MangaRepository.kt b/src/main/kotlin/fr/ziedelth/repositories/MangaRepository.kt
new file mode 100644
index 0000000..8e52cc2
--- /dev/null
+++ b/src/main/kotlin/fr/ziedelth/repositories/MangaRepository.kt
@@ -0,0 +1,47 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.entities.Manga
+import fr.ziedelth.utils.Database
+import org.hibernate.Session
+import java.util.*
+
+class MangaRepository(session: () -> Session = { Database.getSession() }) : AbstractRepository(session),
+ IPageRepository {
+ fun getByEAN(tag: String, ean: Long): Manga? {
+ val session = getSession.invoke()
+ val query = session.createQuery("FROM Manga WHERE anime.country.tag = :tag AND ean = :ean", Manga::class.java)
+ query.maxResults = 1
+ query.setParameter("tag", tag)
+ query.setParameter("ean", ean)
+ val result = query.uniqueResult()
+ session.close()
+ return result
+ }
+
+ override fun getByPage(tag: String, page: Int, limit: Int): List {
+ return super.getByPage(
+ page,
+ limit,
+ "FROM Manga WHERE anime.country.tag = :tag AND ean IS NOT NULL ORDER BY releaseDate DESC, anime.name",
+ "tag" to tag,
+ )
+ }
+
+ override fun getByPageWithAnime(uuid: UUID, page: Int, limit: Int): List {
+ return super.getByPage(
+ page,
+ limit,
+ "FROM Manga WHERE anime.uuid = :uuid ORDER BY releaseDate DESC, anime.name",
+ "uuid" to uuid,
+ )
+ }
+
+ override fun getByPageWithList(list: List, page: Int, limit: Int): List {
+ return super.getByPage(
+ page,
+ limit,
+ "FROM Manga WHERE uuid IN :list ORDER BY releaseDate DESC, anime.name",
+ "list" to list
+ )
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/fr/ziedelth/repositories/NewsRepository.kt b/src/main/kotlin/fr/ziedelth/repositories/NewsRepository.kt
new file mode 100644
index 0000000..55159f3
--- /dev/null
+++ b/src/main/kotlin/fr/ziedelth/repositories/NewsRepository.kt
@@ -0,0 +1,26 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.entities.News
+import fr.ziedelth.utils.Database
+import org.hibernate.Session
+import java.util.*
+
+class NewsRepository(session: () -> Session = { Database.getSession() }) : AbstractRepository(session),
+ IPageRepository {
+ override fun getByPage(tag: String, page: Int, limit: Int): List {
+ return super.getByPage(
+ page,
+ limit,
+ "FROM News WHERE country.tag = :tag ORDER BY releaseDate DESC",
+ "tag" to tag,
+ )
+ }
+
+ override fun getByPageWithAnime(uuid: UUID, page: Int, limit: Int): List {
+ TODO("Not yet implemented")
+ }
+
+ override fun getByPageWithList(list: List, page: Int, limit: Int): List {
+ TODO("Not yet implemented")
+ }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/fr/ziedelth/repositories/PlatformRepository.kt b/src/main/kotlin/fr/ziedelth/repositories/PlatformRepository.kt
new file mode 100644
index 0000000..701fd40
--- /dev/null
+++ b/src/main/kotlin/fr/ziedelth/repositories/PlatformRepository.kt
@@ -0,0 +1,7 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.entities.Platform
+import fr.ziedelth.utils.Database
+import org.hibernate.Session
+
+class PlatformRepository(session: () -> Session = { Database.getSession() }) : AbstractRepository(session)
\ No newline at end of file
diff --git a/src/main/kotlin/fr/ziedelth/repositories/SimulcastRepository.kt b/src/main/kotlin/fr/ziedelth/repositories/SimulcastRepository.kt
new file mode 100644
index 0000000..51d407c
--- /dev/null
+++ b/src/main/kotlin/fr/ziedelth/repositories/SimulcastRepository.kt
@@ -0,0 +1,29 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.entities.Simulcast
+import fr.ziedelth.utils.Database
+import org.hibernate.Session
+
+class SimulcastRepository(session: () -> Session = { Database.getSession() }) : AbstractRepository(session) {
+ fun getAll(tag: String?): List {
+ val session = getSession.invoke()
+ val query = session.createQuery(
+ "SELECT DISTINCT simulcasts FROM Anime WHERE country.tag = :tag",
+ Simulcast::class.java
+ )
+ query.setParameter("tag", tag)
+ val list = query.list()
+ session.close()
+ return list
+ }
+
+ fun findBySeasonAndYear(season: String, year: Int): Simulcast? {
+ val session = getSession.invoke()
+ val query = session.createQuery("FROM Simulcast WHERE season = :season AND year = :year", Simulcast::class.java)
+ query.setParameter("season", season)
+ query.setParameter("year", year)
+ val simulcast = query.uniqueResult()
+ session.close()
+ return simulcast
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/fr/ziedelth/AbstractAPITest.kt b/src/test/kotlin/fr/ziedelth/AbstractAPITest.kt
new file mode 100644
index 0000000..4248ee9
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/AbstractAPITest.kt
@@ -0,0 +1,141 @@
+package fr.ziedelth
+
+import fr.ziedelth.entities.*
+import fr.ziedelth.plugins.*
+import fr.ziedelth.utils.DatabaseTest
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+
+internal abstract class AbstractAPITest {
+ @BeforeEach
+ fun tearUp() {
+ countryRepository.saveAll(
+ listOf(
+ Country(tag = "fr", name = "France"),
+ Country(tag = "jp", name = "Japan")
+ )
+ )
+ val countries = countryRepository.getAll()
+
+ val platform1 = Platform(name = "Netflix", image = "hello", url = "hello")
+ val platform2 = Platform(name = "Crunchyroll", image = "hello", url = "hello")
+ val platform3 = Platform(name = "Wakanim", image = "hello", url = "hello")
+ platformRepository.saveAll(listOf(platform1, platform2, platform3))
+ val platforms = platformRepository.getAll()
+
+ val simulcast1 = Simulcast(season = "WINTER", year = 2020)
+ val simulcast2 = Simulcast(season = "SPRING", year = 2020)
+ simulcastRepository.saveAll(listOf(simulcast1, simulcast2))
+ val simulcasts = simulcastRepository.getAll()
+
+ val genre1 = Genre(name = "Action")
+ val genre2 = Genre(name = "Comedy")
+ val genre3 = Genre(name = "Drama")
+ genreRepository.saveAll(listOf(genre1, genre2, genre3))
+ val genres = genreRepository.getAll()
+
+ val anime1 = Anime(
+ country = countries.first(),
+ name = "One Piece",
+ image = "hello",
+ hashes = mutableSetOf("hello"),
+ simulcasts = mutableSetOf(simulcasts.first()),
+ genres = mutableSetOf(genres.first(), genres.last()),
+ )
+ val anime2 = Anime(
+ country = countries.first(),
+ name = "Naruto",
+ image = "hello",
+ hashes = mutableSetOf("hello2"),
+ simulcasts = mutableSetOf(simulcasts.first()),
+ genres = mutableSetOf(genres.first(), genres.last()),
+ )
+ val anime3 = Anime(
+ country = countries.first(),
+ name = "Bleach",
+ image = "hello",
+ hashes = mutableSetOf("hello3"),
+ simulcasts = mutableSetOf(simulcasts.first()),
+ genres = mutableSetOf(genres.first(), genres.last()),
+ )
+ animeRepository.saveAll(listOf(anime1, anime2, anime3))
+ val animes = animeRepository.getAll()
+
+ val episodeType1 = EpisodeType(name = "Episode")
+ val episodeType2 = EpisodeType(name = "OAV")
+ val episodeType3 = EpisodeType(name = "Film")
+ episodeTypeRepository.saveAll(listOf(episodeType1, episodeType2, episodeType3))
+ val episodeTypes = episodeTypeRepository.getAll()
+
+ val langType1 = LangType(name = "SUBTITLES")
+ val langType2 = LangType(name = "VOICE")
+ langTypeRepository.saveAll(listOf(langType1, langType2))
+ val langTypes = langTypeRepository.getAll()
+
+ animes.forEach {
+ val episodes = (1..10).map { episode ->
+ val platform = platforms.random()
+ val episodeType = episodeTypes.random()
+ val langType = langTypes.random()
+
+ Episode(
+ platform = platform,
+ anime = it,
+ episodeType = episodeType,
+ langType = langType,
+ hash = "EP-$episode-${platform.name}-${episodeType.name}-${langType.name}-${Math.random()}",
+ season = 1,
+ number = episode,
+ url = "hello",
+ image = "hello",
+ duration = 1440
+ )
+ }
+ episodeRepository.saveAll(episodes)
+
+ val mangas = (1..10).map { manga ->
+ val platform = platforms.random()
+
+ Manga(
+ platform = platform,
+ anime = it,
+ hash = "MA-$manga-${platform.name}-${Math.random()}",
+ url = "hello",
+ cover = "hello",
+ editor = "MyEditor $manga",
+ ref = "MyRef $manga",
+ ean = Math.random().toLong(),
+ age = 18,
+ price = 10.0,
+ )
+ }
+ mangaRepository.saveAll(mangas)
+ }
+
+ newsRepository.saveAll(
+ listOf(
+ News(
+ country = countries.first(),
+ platform = platforms.first(),
+ title = "News 1",
+ description = "Content 1",
+ hash = "hello",
+ url = "hello",
+ ),
+ News(
+ country = countries.first(),
+ platform = platforms.first(),
+ title = "News 2",
+ description = "Content 2",
+ hash = "hello2",
+ url = "hello",
+ ),
+ )
+ )
+ }
+
+ @AfterEach
+ fun tearDown() {
+ DatabaseTest.clean()
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/fr/ziedelth/controllers/AnimeControllerTest.kt b/src/test/kotlin/fr/ziedelth/controllers/AnimeControllerTest.kt
new file mode 100644
index 0000000..e8d1306
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/controllers/AnimeControllerTest.kt
@@ -0,0 +1,271 @@
+package fr.ziedelth.controllers
+
+import com.google.gson.Gson
+import com.google.gson.JsonObject
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.Anime
+import fr.ziedelth.entities.Country
+import fr.ziedelth.plugins.*
+import fr.ziedelth.utils.Encoder
+import io.ktor.client.plugins.contentnegotiation.*
+import io.ktor.client.request.*
+import io.ktor.client.statement.*
+import io.ktor.http.*
+import io.ktor.serialization.gson.*
+import io.ktor.server.testing.*
+import io.ktor.util.*
+import org.junit.jupiter.api.Test
+import java.util.*
+import kotlin.test.expect
+
+internal class AnimeControllerTest : AbstractAPITest() {
+ @Test
+ fun searchByHash() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val response = client.get("/animes/country/fr/search/hash/hello")
+ val json = Gson().fromJson(response.bodyAsText(), JsonObject::class.java)
+ val uuid = json.get("uuid").asString
+
+ expect(HttpStatusCode.OK) { response.status }
+ checkNotNull(uuid)
+
+ expect(HttpStatusCode.NotFound) { client.get("/animes/country/fr/search/hash/azertyuiop").status }
+ }
+ }
+
+ @Test
+ fun searchByName() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val response = client.get("/animes/country/fr/search/name/Naruto")
+ val json = Gson().fromJson(response.bodyAsText(), Array::class.java)
+
+ expect(HttpStatusCode.OK) { response.status }
+ expect(1) { json.size }
+ }
+ }
+
+ @Test
+ fun getByPage() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val country = countryRepository.getAll().first()
+ val simulcast = simulcastRepository.getAll().first()
+
+ // NOT CACHED
+
+ val responseNotCached =
+ client.get("/animes/country/${country.tag}/simulcast/${simulcast.uuid}/page/1/limit/12")
+ val jsonNotCached = Gson().fromJson(responseNotCached.bodyAsText(), Array::class.java)
+
+ expect(HttpStatusCode.OK) { responseNotCached.status }
+ expect(3) { jsonNotCached.size }
+
+ // CACHED
+
+ val responseCached =
+ client.get("/animes/country/${country.tag}/simulcast/${simulcast.uuid}/page/1/limit/12")
+ val jsonCached = Gson().fromJson(responseCached.bodyAsText(), Array::class.java)
+
+ expect(HttpStatusCode.OK) { responseCached.status }
+ expect(3) { jsonCached.size }
+ }
+ }
+
+ @Test
+ fun getByPageError() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val country = countryRepository.getAll().first()
+ val simulcast = simulcastRepository.getAll().first()
+
+ // ERROR
+
+ val responseError =
+ client.get("/animes/country/${country.tag}/simulcast/${simulcast.uuid}/page/ae/limit/12")
+
+ expect(HttpStatusCode.InternalServerError) { responseError.status }
+ }
+ }
+
+ @Test
+ fun getWatchlistByPage() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val anime = animeRepository.getAll().first()
+ val bodyRequest = Encoder.toGzip("[\"${anime.uuid}\"]")
+
+ val response = client.post("/animes/watchlist/page/1/limit/12") {
+ setBody(bodyRequest)
+ }
+
+ val json = Gson().fromJson(response.bodyAsText(), Array::class.java)
+
+ expect(HttpStatusCode.OK) { response.status }
+ expect(1) { json.size }
+ }
+ }
+
+ @Test
+ fun getWatchlistByPageError() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val anime = animeRepository.getAll().first()
+ val bodyRequest = Encoder.toGzip("[\"${anime.uuid}\"]")
+
+ val responseError = client.post("/animes/watchlist/page/ae/limit/12") {
+ setBody(bodyRequest)
+ }
+
+ expect(HttpStatusCode.InternalServerError) { responseError.status }
+ }
+ }
+
+ @Test
+ fun create() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val country = countryRepository.getAll().first()
+
+ val response = client.post("/animes") {
+ contentType(ContentType.Application.Json)
+ setBody(Anime(country = country, name = "Test", description = "Test", image = "Test"))
+ }
+
+ expect(HttpStatusCode.Created) { response.status }
+ val json = Gson().fromJson(response.bodyAsText(), Anime::class.java)
+ checkNotNull(json.uuid)
+ }
+ }
+
+ @Test
+ fun createError() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val country = countryRepository.getAll().first()
+
+ expect(HttpStatusCode.BadRequest) {
+ client.post("/animes") {
+ contentType(ContentType.Application.Json)
+ setBody(
+ Anime(
+ country = Country(tag = "us", name = "United States"),
+ name = "Test",
+ description = "Test",
+ image = "Test"
+ )
+ )
+ }.status
+ }
+
+ expect(HttpStatusCode.BadRequest) {
+ client.post("/animes") {
+ contentType(ContentType.Application.Json)
+ setBody(Anime(country = country, description = "Test", image = "Test"))
+ }.status
+ }
+
+ expect(HttpStatusCode.Conflict) {
+ client.post("/animes") {
+ contentType(ContentType.Application.Json)
+ setBody(Anime(country = country, name = "One Piece", description = "Test", image = "Test"))
+ }.status
+ }
+ }
+ }
+
+ @Test
+ fun merge() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val animes = animeRepository.getAll()
+ val uuids = animes.map { it.uuid.toString() }
+
+ val response = client.put("/animes/merge") {
+ contentType(ContentType.Application.Json)
+ setBody(uuids)
+ }
+
+ expect(HttpStatusCode.OK) { response.status }
+ expect(1) { animeRepository.getAll().size }
+ }
+ }
+
+ @Test
+ fun mergeError() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ expect(HttpStatusCode.NotFound) {
+ client.put("/animes/merge") {
+ contentType(ContentType.Application.Json)
+ setBody(emptyList())
+ }.status
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/fr/ziedelth/controllers/CountryControllerTest.kt b/src/test/kotlin/fr/ziedelth/controllers/CountryControllerTest.kt
new file mode 100644
index 0000000..32b41a0
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/controllers/CountryControllerTest.kt
@@ -0,0 +1,95 @@
+package fr.ziedelth.controllers
+
+import com.google.gson.Gson
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.Country
+import fr.ziedelth.plugins.*
+import io.ktor.client.plugins.contentnegotiation.*
+import io.ktor.client.request.*
+import io.ktor.client.statement.*
+import io.ktor.http.*
+import io.ktor.serialization.gson.*
+import io.ktor.server.testing.*
+import io.ktor.util.*
+import org.junit.jupiter.api.Test
+import java.util.*
+import kotlin.test.expect
+
+internal class CountryControllerTest : AbstractAPITest() {
+ @Test
+ fun getAll() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val response = client.get("/countries")
+ expect(HttpStatusCode.OK) { response.status }
+ val json = Gson().fromJson(response.bodyAsText(), Array::class.java)
+ expect(2) { json.size }
+ }
+ }
+
+ @Test
+ fun create() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val response = client.post("/countries") {
+ contentType(ContentType.Application.Json)
+ setBody(Country(tag = "us", name = "United States"))
+ }
+
+ expect(HttpStatusCode.Created) { response.status }
+ val json = Gson().fromJson(response.bodyAsText(), Country::class.java)
+ checkNotNull(json.uuid)
+ }
+ }
+
+ @Test
+ fun createError() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ expect(HttpStatusCode.BadRequest) {
+ client.post("/countries") {
+ contentType(ContentType.Application.Json)
+ setBody(Country(name = "France"))
+ }.status
+ }
+
+ expect(HttpStatusCode.Conflict) {
+ client.post("/countries") {
+ contentType(ContentType.Application.Json)
+ setBody(Country(tag = "fr", name = "Test"))
+ }.status
+ }
+
+ expect(HttpStatusCode.Conflict) {
+ client.post("/countries") {
+ contentType(ContentType.Application.Json)
+ setBody(Country(tag = "test", name = "France"))
+ }.status
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/fr/ziedelth/controllers/EpisodeControllerTest.kt b/src/test/kotlin/fr/ziedelth/controllers/EpisodeControllerTest.kt
new file mode 100644
index 0000000..3cce111
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/controllers/EpisodeControllerTest.kt
@@ -0,0 +1,327 @@
+package fr.ziedelth.controllers
+
+import com.google.gson.Gson
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.*
+import fr.ziedelth.plugins.*
+import fr.ziedelth.utils.Encoder
+import io.ktor.client.plugins.contentnegotiation.*
+import io.ktor.client.request.*
+import io.ktor.client.statement.*
+import io.ktor.http.*
+import io.ktor.serialization.gson.*
+import io.ktor.server.testing.*
+import io.ktor.util.*
+import org.junit.jupiter.api.Test
+import java.util.*
+import kotlin.test.expect
+
+internal class EpisodeControllerTest : AbstractAPITest() {
+ @Test
+ fun getByPage() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val country = countryRepository.getAll().first()
+
+ // NOT CACHED
+
+ val responseNotCached =
+ client.get("/episodes/country/${country.tag}/page/1/limit/12")
+ val jsonNotCached = Gson().fromJson(responseNotCached.bodyAsText(), Array::class.java)
+
+ expect(HttpStatusCode.OK) { responseNotCached.status }
+ expect(12) { jsonNotCached.size }
+
+ // CACHED
+
+ val responseCached =
+ client.get("/episodes/country/${country.tag}/page/1/limit/12")
+ val jsonCached = Gson().fromJson(responseCached.bodyAsText(), Array::class.java)
+
+ expect(HttpStatusCode.OK) { responseCached.status }
+ expect(12) { jsonCached.size }
+ }
+ }
+
+ @Test
+ fun getByPageError() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val country = countryRepository.getAll().first()
+
+ // ERROR
+
+ expect(HttpStatusCode.InternalServerError) { client.get("/episodes/country/${country.tag}/page/ae/limit/12").status }
+ expect(HttpStatusCode.InternalServerError) { client.get("/episodes/country/${country.tag}/page/1/limit/ae").status }
+ expect(HttpStatusCode.InternalServerError) { client.get("/episodes/country/${country.tag}/page/0/limit/12").status }
+ expect(HttpStatusCode.InternalServerError) { client.get("/episodes/country/${country.tag}/page/1/limit/0").status }
+ expect(HttpStatusCode.InternalServerError) { client.get("/episodes/country/${country.tag}/page/1/limit/31").status }
+ }
+ }
+
+ @Test
+ fun getByPageWithAnime() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val anime = animeRepository.getAll().first()
+
+ val response =
+ client.get("/episodes/anime/${anime.uuid}/page/1/limit/12")
+ val json = Gson().fromJson(response.bodyAsText(), Array::class.java)
+
+ expect(HttpStatusCode.OK) { response.status }
+ expect(10) { json.size }
+ }
+ }
+
+ @Test
+ fun getByPageWithAnimeError() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val anime = animeRepository.getAll().first()
+
+ // ERROR
+
+ val responseError =
+ client.get("/episodes/anime/${anime.uuid}/page/ae/limit/12")
+
+ expect(HttpStatusCode.InternalServerError) { responseError.status }
+ }
+ }
+
+ @Test
+ fun getWatchlistByPage() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val anime = animeRepository.getAll().first()
+ val bodyRequest = Encoder.toGzip("[\"${anime.uuid}\"]")
+
+ val response = client.post("/episodes/watchlist/page/1/limit/12") {
+ setBody(bodyRequest)
+ }
+
+ val json = Gson().fromJson(response.bodyAsText(), Array::class.java)
+
+ expect(HttpStatusCode.OK) { response.status }
+ expect(10) { json.size }
+ }
+ }
+
+ @Test
+ fun getWatchlistByPageError() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val anime = animeRepository.getAll().first()
+ val bodyRequest = Encoder.toGzip("[\"${anime.uuid}\"]")
+
+ val responseError = client.post("/episodes/watchlist/page/ae/limit/12") {
+ setBody(bodyRequest)
+ }
+
+ expect(HttpStatusCode.InternalServerError) { responseError.status }
+ }
+ }
+
+ @Test
+ fun save() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val platform = platformRepository.getAll().first()
+ val anime = animeRepository.getAll().first()
+ val episodeType = episodeTypeRepository.getAll().first()
+ val langType = langTypeRepository.getAll().first()
+
+ val response = client.post("/episodes/multiple") {
+ contentType(ContentType.Application.Json)
+ setBody(
+ listOf(
+ Episode(
+ anime = anime,
+ platform = platform,
+ episodeType = episodeType,
+ langType = langType,
+ number = 1,
+ season = 1,
+ url = "https://www.google.com",
+ image = "https://www.google.com",
+ hash = "hash",
+ ),
+ Episode(
+ anime = anime,
+ platform = platform,
+ episodeType = episodeType,
+ langType = langType,
+ number = 2,
+ season = 1,
+ url = "https://www.google.com",
+ image = "https://www.google.com",
+ hash = "azertyuiop",
+ )
+ )
+ )
+ }
+
+ expect(HttpStatusCode.Created) { response.status }
+ val json = Gson().fromJson(response.bodyAsText(), Array::class.java)
+ expect(2) { json.size }
+ }
+ }
+
+ @Test
+ fun saveError() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ expect(HttpStatusCode.InternalServerError) {
+ client.post("/episodes/multiple") {
+ contentType(ContentType.Application.Json)
+ setBody(
+ listOf(
+ Episode(
+ platform = Platform(),
+ anime = Anime(),
+ episodeType = EpisodeType(),
+ langType = LangType(),
+ number = 1,
+ season = 1,
+ url = "https://www.google.com",
+ image = "https://www.google.com",
+ ),
+ )
+ )
+ }.status
+ }
+
+ val platform = platformRepository.getAll().first()
+
+ expect(HttpStatusCode.InternalServerError) {
+ client.post("/episodes/multiple") {
+ contentType(ContentType.Application.Json)
+ setBody(
+ listOf(
+ Episode(
+ platform = platform,
+ anime = Anime(),
+ episodeType = EpisodeType(),
+ langType = LangType(),
+ number = 1,
+ season = 1,
+ url = "https://www.google.com",
+ image = "https://www.google.com",
+ ),
+ )
+ )
+ }.status
+ }
+
+ val anime = animeRepository.getAll().first()
+
+ expect(HttpStatusCode.InternalServerError) {
+ client.post("/episodes/multiple") {
+ contentType(ContentType.Application.Json)
+ setBody(
+ listOf(
+ Episode(
+ platform = platform,
+ anime = anime,
+ episodeType = EpisodeType(),
+ langType = LangType(),
+ number = 1,
+ season = 1,
+ url = "https://www.google.com",
+ image = "https://www.google.com",
+ ),
+ )
+ )
+ }.status
+ }
+
+ val episodeType = episodeTypeRepository.getAll().first()
+
+ expect(HttpStatusCode.InternalServerError) {
+ client.post("/episodes/multiple") {
+ contentType(ContentType.Application.Json)
+ setBody(
+ listOf(
+ Episode(
+ platform = platform,
+ anime = anime,
+ episodeType = episodeType,
+ langType = LangType(),
+ number = 1,
+ season = 1,
+ url = "https://www.google.com",
+ image = "https://www.google.com",
+ ),
+ )
+ )
+ }.status
+ }
+
+ val langType = langTypeRepository.getAll().first()
+
+ expect(HttpStatusCode.InternalServerError) {
+ client.post("/episodes/multiple") {
+ contentType(ContentType.Application.Json)
+ setBody(
+ listOf(
+ Episode(
+ platform = platform,
+ anime = anime,
+ episodeType = episodeType,
+ langType = langType,
+ number = 1,
+ season = 1,
+ url = "https://www.google.com",
+ image = "https://www.google.com",
+ ),
+ )
+ )
+ }.status
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/fr/ziedelth/controllers/EpisodeTypeControllerTest.kt b/src/test/kotlin/fr/ziedelth/controllers/EpisodeTypeControllerTest.kt
new file mode 100644
index 0000000..3c112d9
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/controllers/EpisodeTypeControllerTest.kt
@@ -0,0 +1,88 @@
+package fr.ziedelth.controllers
+
+import com.google.gson.Gson
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.EpisodeType
+import fr.ziedelth.plugins.*
+import io.ktor.client.plugins.contentnegotiation.*
+import io.ktor.client.request.*
+import io.ktor.client.statement.*
+import io.ktor.http.*
+import io.ktor.serialization.gson.*
+import io.ktor.server.testing.*
+import io.ktor.util.*
+import org.junit.jupiter.api.Test
+import java.util.*
+import kotlin.test.expect
+
+internal class EpisodeTypeControllerTest : AbstractAPITest() {
+ @Test
+ fun getAll() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val response = client.get("/episodetypes")
+ expect(HttpStatusCode.OK) { response.status }
+ val json = Gson().fromJson(response.bodyAsText(), Array::class.java)
+ expect(3) { json.size }
+ }
+ }
+
+ @Test
+ fun create() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val response = client.post("/episodetypes") {
+ contentType(ContentType.Application.Json)
+ setBody(EpisodeType(name = "test"))
+ }
+
+ expect(HttpStatusCode.Created) { response.status }
+ val json = Gson().fromJson(response.bodyAsText(), EpisodeType::class.java)
+ checkNotNull(json.uuid)
+ }
+ }
+
+ @Test
+ fun createError() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ expect(HttpStatusCode.BadRequest) {
+ client.post("/episodetypes") {
+ contentType(ContentType.Application.Json)
+ setBody(EpisodeType())
+ }.status
+ }
+
+ expect(HttpStatusCode.Conflict) {
+ client.post("/episodetypes") {
+ contentType(ContentType.Application.Json)
+ setBody(EpisodeType(name = "Episode"))
+ }.status
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/fr/ziedelth/controllers/GenreControllerTest.kt b/src/test/kotlin/fr/ziedelth/controllers/GenreControllerTest.kt
new file mode 100644
index 0000000..3f15512
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/controllers/GenreControllerTest.kt
@@ -0,0 +1,88 @@
+package fr.ziedelth.controllers
+
+import com.google.gson.Gson
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.Genre
+import fr.ziedelth.plugins.*
+import io.ktor.client.plugins.contentnegotiation.*
+import io.ktor.client.request.*
+import io.ktor.client.statement.*
+import io.ktor.http.*
+import io.ktor.serialization.gson.*
+import io.ktor.server.testing.*
+import io.ktor.util.*
+import org.junit.jupiter.api.Test
+import java.util.*
+import kotlin.test.expect
+
+internal class GenreControllerTest : AbstractAPITest() {
+ @Test
+ fun getAll() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val response = client.get("/genres")
+ expect(HttpStatusCode.OK) { response.status }
+ val json = Gson().fromJson(response.bodyAsText(), Array::class.java)
+ expect(3) { json.size }
+ }
+ }
+
+ @Test
+ fun create() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val response = client.post("/genres") {
+ contentType(ContentType.Application.Json)
+ setBody(Genre(name = "test"))
+ }
+
+ expect(HttpStatusCode.Created) { response.status }
+ val json = Gson().fromJson(response.bodyAsText(), Genre::class.java)
+ checkNotNull(json.uuid)
+ }
+ }
+
+ @Test
+ fun createError() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ expect(HttpStatusCode.BadRequest) {
+ client.post("/genres") {
+ contentType(ContentType.Application.Json)
+ setBody(Genre())
+ }.status
+ }
+
+ expect(HttpStatusCode.Conflict) {
+ client.post("/genres") {
+ contentType(ContentType.Application.Json)
+ setBody(Genre(name = "Action"))
+ }.status
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/fr/ziedelth/controllers/LangTypeControllerTest.kt b/src/test/kotlin/fr/ziedelth/controllers/LangTypeControllerTest.kt
new file mode 100644
index 0000000..83c3dc6
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/controllers/LangTypeControllerTest.kt
@@ -0,0 +1,88 @@
+package fr.ziedelth.controllers
+
+import com.google.gson.Gson
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.LangType
+import fr.ziedelth.plugins.*
+import io.ktor.client.plugins.contentnegotiation.*
+import io.ktor.client.request.*
+import io.ktor.client.statement.*
+import io.ktor.http.*
+import io.ktor.serialization.gson.*
+import io.ktor.server.testing.*
+import io.ktor.util.*
+import org.junit.jupiter.api.Test
+import java.util.*
+import kotlin.test.expect
+
+internal class LangTypeControllerTest : AbstractAPITest() {
+ @Test
+ fun getAll() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val response = client.get("/langtypes")
+ expect(HttpStatusCode.OK) { response.status }
+ val json = Gson().fromJson(response.bodyAsText(), Array::class.java)
+ expect(2) { json.size }
+ }
+ }
+
+ @Test
+ fun create() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val response = client.post("/langtypes") {
+ contentType(ContentType.Application.Json)
+ setBody(LangType(name = "test"))
+ }
+
+ expect(HttpStatusCode.Created) { response.status }
+ val json = Gson().fromJson(response.bodyAsText(), LangType::class.java)
+ checkNotNull(json.uuid)
+ }
+ }
+
+ @Test
+ fun createError() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ expect(HttpStatusCode.BadRequest) {
+ client.post("/langtypes") {
+ contentType(ContentType.Application.Json)
+ setBody(LangType())
+ }.status
+ }
+
+ expect(HttpStatusCode.Conflict) {
+ client.post("/langtypes") {
+ contentType(ContentType.Application.Json)
+ setBody(LangType(name = "SUBTITLES"))
+ }.status
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/fr/ziedelth/controllers/MangaControllerTest.kt b/src/test/kotlin/fr/ziedelth/controllers/MangaControllerTest.kt
new file mode 100644
index 0000000..268ffd5
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/controllers/MangaControllerTest.kt
@@ -0,0 +1,306 @@
+package fr.ziedelth.controllers
+
+import com.google.gson.Gson
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.*
+import fr.ziedelth.plugins.*
+import fr.ziedelth.utils.Encoder
+import io.ktor.client.plugins.contentnegotiation.*
+import io.ktor.client.request.*
+import io.ktor.client.statement.*
+import io.ktor.http.*
+import io.ktor.serialization.gson.*
+import io.ktor.server.testing.*
+import io.ktor.util.*
+import org.junit.jupiter.api.Test
+import java.util.*
+import kotlin.test.expect
+
+internal class MangaControllerTest : AbstractAPITest() {
+ @Test
+ fun searchByEAN() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val country = countryRepository.getAll().first()
+ val ean = mangaRepository.getAll().first().ean
+
+ val responseNotCached = client.get("/mangas/country/${country.tag}/search/ean/$ean")
+ val json = Gson().fromJson(responseNotCached.bodyAsText(), Manga::class.java)
+
+ expect(HttpStatusCode.OK) { responseNotCached.status }
+ checkNotNull(json.uuid)
+ }
+ }
+
+ @Test
+ fun getByPage() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val country = countryRepository.getAll().first()
+
+ // NOT CACHED
+
+ val responseNotCached =
+ client.get("/mangas/country/${country.tag}/page/1/limit/12")
+ val jsonNotCached = Gson().fromJson(responseNotCached.bodyAsText(), Array::class.java)
+
+ expect(HttpStatusCode.OK) { responseNotCached.status }
+ expect(12) { jsonNotCached.size }
+
+ // CACHED
+
+ val responseCached =
+ client.get("/mangas/country/${country.tag}/page/1/limit/12")
+ val jsonCached = Gson().fromJson(responseCached.bodyAsText(), Array::class.java)
+
+ expect(HttpStatusCode.OK) { responseCached.status }
+ expect(12) { jsonCached.size }
+ }
+ }
+
+ @Test
+ fun getByPageError() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val country = countryRepository.getAll().first()
+
+ // ERROR
+
+ val responseError =
+ client.get("/mangas/country/${country.tag}/page/ae/limit/12")
+
+ expect(HttpStatusCode.InternalServerError) { responseError.status }
+ }
+ }
+
+ @Test
+ fun getByPageWithAnime() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val anime = animeRepository.getAll().first()
+
+ val response =
+ client.get("/mangas/anime/${anime.uuid}/page/1/limit/12")
+ val json = Gson().fromJson(response.bodyAsText(), Array::class.java)
+
+ expect(HttpStatusCode.OK) { response.status }
+ expect(10) { json.size }
+ }
+ }
+
+ @Test
+ fun getByPageWithAnimeError() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val anime = animeRepository.getAll().first()
+
+ // ERROR
+
+ val responseError =
+ client.get("/mangas/anime/${anime.uuid}/page/ae/limit/12")
+
+ expect(HttpStatusCode.InternalServerError) { responseError.status }
+ }
+ }
+
+ @Test
+ fun getWatchlistByPage() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val manga = mangaRepository.getAll().first()
+ val bodyRequest = Encoder.toGzip("[\"${manga.uuid}\"]")
+
+ val response = client.post("/mangas/watchlist/page/1/limit/12") {
+ setBody(bodyRequest)
+ }
+
+ val json = Gson().fromJson(response.bodyAsText(), Array::class.java)
+
+ expect(HttpStatusCode.OK) { response.status }
+ expect(1) { json.size }
+ }
+ }
+
+ @Test
+ fun getWatchlistByPageError() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val manga = mangaRepository.getAll().first()
+ val bodyRequest = Encoder.toGzip("[\"${manga.uuid}\"]")
+
+ val responseError = client.post("/mangas/watchlist/page/ae/limit/12") {
+ setBody(bodyRequest)
+ }
+
+ expect(HttpStatusCode.InternalServerError) { responseError.status }
+ }
+ }
+
+ @Test
+ fun save() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val platform = platformRepository.getAll().first()
+ val anime = animeRepository.getAll().first()
+
+ val response = client.post("/mangas/multiple") {
+ contentType(ContentType.Application.Json)
+ setBody(
+ listOf(
+ Manga(
+ platform = platform,
+ anime = anime,
+ hash = "hash",
+ url = "test",
+ cover = "test",
+ editor = "test",
+ ref = "test",
+ ean = Math.random().toLong(),
+ age = 12,
+ price = 7.5,
+ ),
+ Manga(
+ platform = platform,
+ anime = anime,
+ hash = "hash2",
+ url = "test2",
+ cover = "test2",
+ editor = "test2",
+ ref = "test2",
+ ean = Math.random().toLong(),
+ age = 12,
+ price = 7.5,
+ )
+ )
+ )
+ }
+
+ expect(HttpStatusCode.Created) { response.status }
+ val json = Gson().fromJson(response.bodyAsText(), Array::class.java)
+ expect(2) { json.size }
+ }
+ }
+
+ @Test
+ fun saveError() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ expect(HttpStatusCode.InternalServerError) {
+ client.post("/mangas/multiple") {
+ contentType(ContentType.Application.Json)
+ setBody(
+ listOf(
+ Manga(
+ platform = Platform(),
+ anime = Anime(),
+ hash = "hash2",
+ url = "test2",
+ cover = "test2",
+ editor = "test2",
+ ref = "test2",
+ ean = Math.random().toLong(),
+ age = 12,
+ price = 7.5,
+ ),
+ )
+ )
+ }.status
+ }
+
+ val platform = platformRepository.getAll().first()
+
+ expect(HttpStatusCode.InternalServerError) {
+ client.post("/mangas/multiple") {
+ contentType(ContentType.Application.Json)
+ setBody(
+ listOf(
+ Manga(
+ platform = platform,
+ anime = Anime(),
+ hash = "hash2",
+ url = "test2",
+ cover = "test2",
+ editor = "test2",
+ ref = "test2",
+ ean = Math.random().toLong(),
+ age = 12,
+ price = 7.5,
+ ),
+ )
+ )
+ }.status
+ }
+
+ val anime = animeRepository.getAll().first()
+
+ expect(HttpStatusCode.InternalServerError) {
+ client.post("/episodes/multiple") {
+ contentType(ContentType.Application.Json)
+ setBody(
+ listOf(
+ Manga(
+ platform = platform,
+ anime = anime,
+ url = "test2",
+ cover = "test2",
+ editor = "test2",
+ ref = "test2",
+ ean = Math.random().toLong(),
+ age = 12,
+ price = 7.5,
+ ),
+ )
+ )
+ }.status
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/fr/ziedelth/controllers/NewsControllerTest.kt b/src/test/kotlin/fr/ziedelth/controllers/NewsControllerTest.kt
new file mode 100644
index 0000000..5934290
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/controllers/NewsControllerTest.kt
@@ -0,0 +1,187 @@
+package fr.ziedelth.controllers
+
+import com.google.gson.Gson
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.*
+import fr.ziedelth.plugins.*
+import io.ktor.client.plugins.contentnegotiation.*
+import io.ktor.client.request.*
+import io.ktor.client.statement.*
+import io.ktor.http.*
+import io.ktor.serialization.gson.*
+import io.ktor.server.testing.*
+import io.ktor.util.*
+import org.junit.jupiter.api.Test
+import java.util.*
+import kotlin.test.expect
+
+internal class NewsControllerTest : AbstractAPITest() {
+ @Test
+ fun getByPage() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val country = countryRepository.getAll().first()
+
+ // NOT CACHED
+
+ val responseNotCached =
+ client.get("/news/country/${country.tag}/page/1/limit/12")
+ val jsonNotCached = Gson().fromJson(responseNotCached.bodyAsText(), Array::class.java)
+
+ expect(HttpStatusCode.OK) { responseNotCached.status }
+ expect(2) { jsonNotCached.size }
+
+ // CACHED
+
+ val responseCached =
+ client.get("/news/country/${country.tag}/page/1/limit/12")
+ val jsonCached = Gson().fromJson(responseCached.bodyAsText(), Array::class.java)
+
+ expect(HttpStatusCode.OK) { responseCached.status }
+ expect(2) { jsonCached.size }
+ }
+ }
+
+ @Test
+ fun getByPageError() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val country = countryRepository.getAll().first()
+
+ // ERROR
+
+ val responseError =
+ client.get("/news/country/${country.tag}/page/ae/limit/12")
+
+ expect(HttpStatusCode.InternalServerError) { responseError.status }
+ }
+ }
+
+ @Test
+ fun save() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val platform = platformRepository.getAll().first()
+ val country = countryRepository.getAll().first()
+
+ val response = client.post("/news/multiple") {
+ contentType(ContentType.Application.Json)
+ setBody(
+ listOf(
+ News(
+ country = country,
+ platform = platform,
+ title = "News 3",
+ description = "Content 3",
+ hash = "hello3",
+ url = "hello",
+ ),
+ News(
+ country = country,
+ platform = platform,
+ title = "News 4",
+ description = "Content 4",
+ hash = "hello4",
+ url = "hello",
+ ),
+ )
+ )
+ }
+
+ expect(HttpStatusCode.Created) { response.status }
+ val json = Gson().fromJson(response.bodyAsText(), Array::class.java)
+ expect(2) { json.size }
+ }
+ }
+
+ @Test
+ fun saveError() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ expect(HttpStatusCode.InternalServerError) {
+ client.post("/news/multiple") {
+ contentType(ContentType.Application.Json)
+ setBody(
+ listOf(
+ News(
+ country = Country(),
+ platform = Platform(),
+ title = "News 3",
+ description = "Content 3",
+ hash = "hello3",
+ url = "hello",
+ ),
+ )
+ )
+ }.status
+ }
+
+ val platform = platformRepository.getAll().first()
+
+ expect(HttpStatusCode.InternalServerError) {
+ client.post("/news/multiple") {
+ contentType(ContentType.Application.Json)
+ setBody(
+ listOf(
+ News(
+ country = Country(),
+ platform = platform,
+ title = "News 3",
+ description = "Content 3",
+ hash = "hello3",
+ url = "hello",
+ ),
+ )
+ )
+ }.status
+ }
+
+ val country = countryRepository.getAll().first()
+
+ expect(HttpStatusCode.InternalServerError) {
+ client.post("/news/multiple") {
+ contentType(ContentType.Application.Json)
+ setBody(
+ listOf(
+ News(
+ country = country,
+ platform = platform,
+ title = "News 3",
+ description = "Content 3",
+ url = "hello",
+ ),
+ )
+ )
+ }.status
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/fr/ziedelth/controllers/PlatformControllerTest.kt b/src/test/kotlin/fr/ziedelth/controllers/PlatformControllerTest.kt
new file mode 100644
index 0000000..d2c6975
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/controllers/PlatformControllerTest.kt
@@ -0,0 +1,102 @@
+package fr.ziedelth.controllers
+
+import com.google.gson.Gson
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.Platform
+import fr.ziedelth.plugins.*
+import io.ktor.client.plugins.contentnegotiation.*
+import io.ktor.client.request.*
+import io.ktor.client.statement.*
+import io.ktor.http.*
+import io.ktor.serialization.gson.*
+import io.ktor.server.testing.*
+import io.ktor.util.*
+import org.junit.jupiter.api.Test
+import java.util.*
+import kotlin.test.expect
+
+internal class PlatformControllerTest : AbstractAPITest() {
+ @Test
+ fun getAll() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val response = client.get("/platforms")
+ expect(HttpStatusCode.OK) { response.status }
+ val json = Gson().fromJson(response.bodyAsText(), Array::class.java)
+ expect(3) { json.size }
+ }
+ }
+
+ @Test
+ fun create() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val response = client.post("/platforms") {
+ contentType(ContentType.Application.Json)
+ setBody(Platform(name = "MangaNews", url = "hello", image = "hello"))
+ }
+
+ expect(HttpStatusCode.Created) { response.status }
+ val json = Gson().fromJson(response.bodyAsText(), Platform::class.java)
+ checkNotNull(json.uuid)
+ }
+ }
+
+ @Test
+ fun createError() {
+ testApplication {
+ val client = createClient {
+ install(ContentNegotiation) {
+ gson()
+ }
+ }
+
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ expect(HttpStatusCode.BadRequest) {
+ client.post("/platforms") {
+ contentType(ContentType.Application.Json)
+ setBody(Platform(name = "MangaNews"))
+ }.status
+ }
+
+ expect(HttpStatusCode.BadRequest) {
+ client.post("/platforms") {
+ contentType(ContentType.Application.Json)
+ setBody(Platform(url = "hello"))
+ }.status
+ }
+
+ expect(HttpStatusCode.BadRequest) {
+ client.post("/platforms") {
+ contentType(ContentType.Application.Json)
+ setBody(Platform(image = "hello"))
+ }.status
+ }
+
+ expect(HttpStatusCode.Conflict) {
+ client.post("/platforms") {
+ contentType(ContentType.Application.Json)
+ setBody(Platform(name = "Netflix", url = "hello", image = "hello"))
+ }.status
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/fr/ziedelth/controllers/SimulcastControllerTest.kt b/src/test/kotlin/fr/ziedelth/controllers/SimulcastControllerTest.kt
new file mode 100644
index 0000000..96e27bd
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/controllers/SimulcastControllerTest.kt
@@ -0,0 +1,35 @@
+package fr.ziedelth.controllers
+
+import com.google.gson.Gson
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.Simulcast
+import fr.ziedelth.plugins.*
+import io.ktor.client.plugins.contentnegotiation.*
+import io.ktor.client.request.*
+import io.ktor.client.statement.*
+import io.ktor.http.*
+import io.ktor.serialization.gson.*
+import io.ktor.server.testing.*
+import io.ktor.util.*
+import org.junit.jupiter.api.Test
+import java.util.*
+import kotlin.test.expect
+
+internal class SimulcastControllerTest : AbstractAPITest() {
+ @Test
+ fun getAll() {
+ testApplication {
+ application {
+ configureHTTP()
+ configureRoutingTest()
+ }
+
+ val country = countryRepository.getAll().first()
+
+ val response = client.get("/simulcasts/country/${country.tag}")
+ expect(HttpStatusCode.OK) { response.status }
+ val json = Gson().fromJson(response.bodyAsText(), Array::class.java)
+ expect(1) { json.size }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/fr/ziedelth/entities/AnimeTest.kt b/src/test/kotlin/fr/ziedelth/entities/AnimeTest.kt
new file mode 100644
index 0000000..36a93fe
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/entities/AnimeTest.kt
@@ -0,0 +1,17 @@
+package fr.ziedelth.entities
+
+import org.junit.jupiter.api.Test
+import kotlin.test.expect
+
+class AnimeTest {
+ @Test
+ fun hash() {
+ val anime = Anime(
+ name = "Do It Yourself!!",
+ image = "hello",
+ country = Country(tag = "fr", name = "France")
+ )
+
+ expect("do-it-yourself") { anime.hash() }
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/fr/ziedelth/entities/SimulcastTest.kt b/src/test/kotlin/fr/ziedelth/entities/SimulcastTest.kt
new file mode 100644
index 0000000..beb9f1c
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/entities/SimulcastTest.kt
@@ -0,0 +1,13 @@
+package fr.ziedelth.entities
+
+import org.junit.jupiter.api.Test
+import kotlin.test.expect
+
+class SimulcastTest {
+ @Test
+ fun hash() {
+ val simulcast = Simulcast.getSimulcast(2022, 11)
+ expect(2022) { simulcast.year }
+ expect("AUTUMN") { simulcast.season }
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/fr/ziedelth/plugins/RoutingTest.kt b/src/test/kotlin/fr/ziedelth/plugins/RoutingTest.kt
new file mode 100644
index 0000000..879aac3
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/plugins/RoutingTest.kt
@@ -0,0 +1,40 @@
+package fr.ziedelth.plugins
+
+import fr.ziedelth.controllers.*
+import fr.ziedelth.repositories.*
+import fr.ziedelth.utils.DatabaseTest
+import io.ktor.server.application.*
+import io.ktor.server.routing.*
+
+val countryRepository = CountryRepository { DatabaseTest.getSession() }
+val platformRepository = PlatformRepository { DatabaseTest.getSession() }
+val simulcastRepository = SimulcastRepository { DatabaseTest.getSession() }
+val genreRepository = GenreRepository { DatabaseTest.getSession() }
+val animeRepository = AnimeRepository { DatabaseTest.getSession() }
+val episodeTypeRepository = EpisodeTypeRepository { DatabaseTest.getSession() }
+val langTypeRepository = LangTypeRepository { DatabaseTest.getSession() }
+val episodeRepository = EpisodeRepository { DatabaseTest.getSession() }
+val mangaRepository = MangaRepository { DatabaseTest.getSession() }
+val newsRepository = NewsRepository { DatabaseTest.getSession() }
+
+fun Application.configureRoutingTest() {
+ routing {
+ CountryController(countryRepository).getRoutes(this)
+ PlatformController(platformRepository).getRoutes(this)
+ SimulcastController(simulcastRepository).getRoutes(this)
+ GenreController(genreRepository).getRoutes(this)
+ AnimeController(countryRepository, animeRepository, episodeRepository, mangaRepository).getRoutes(this)
+ EpisodeTypeController(episodeTypeRepository).getRoutes(this)
+ LangTypeController(langTypeRepository).getRoutes(this)
+ EpisodeController(
+ platformRepository,
+ animeRepository,
+ simulcastRepository,
+ episodeTypeRepository,
+ langTypeRepository,
+ episodeRepository
+ ).getRoutes(this)
+ NewsController(countryRepository, platformRepository, newsRepository).getRoutes(this)
+ MangaController(platformRepository, animeRepository, mangaRepository).getRoutes(this)
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/fr/ziedelth/repositories/AnimeRepositoryTest.kt b/src/test/kotlin/fr/ziedelth/repositories/AnimeRepositoryTest.kt
new file mode 100644
index 0000000..4a6d15c
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/repositories/AnimeRepositoryTest.kt
@@ -0,0 +1,173 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.Anime
+import fr.ziedelth.entities.Country
+import fr.ziedelth.plugins.animeRepository
+import fr.ziedelth.plugins.countryRepository
+import fr.ziedelth.plugins.simulcastRepository
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertThrows
+import java.util.*
+import kotlin.test.expect
+
+internal class AnimeRepositoryTest : AbstractAPITest() {
+ @Test
+ fun find() {
+ val anime = animeRepository.find(UUID.randomUUID())
+ expect(null) { anime }
+
+ val animes = animeRepository.getAll()
+ expect(animes.first().uuid) { animeRepository.find(animes.first().uuid)?.uuid }
+ }
+
+ @Test
+ fun exists() {
+ expect(true) { animeRepository.exists("name", "One Piece") }
+ expect(false) { animeRepository.exists("uuid", UUID.randomUUID()) }
+ }
+
+ @Test
+ fun findAll() {
+ expect(emptyList()) { animeRepository.findAll(listOf(UUID.randomUUID())) }
+
+ val animes = animeRepository.getAll()
+ val list = animeRepository.findAll(listOf(animes.first().uuid, animes[1].uuid))
+
+ expect(true) { list.any { it.uuid == animes.first().uuid } && list.any { it.uuid == animes[1].uuid } }
+ expect(false) { list.any { it.uuid == animes[2].uuid } }
+ }
+
+ @Test
+ fun getAll() {
+ expect(3) { animeRepository.getAll().size }
+ }
+
+ @Test
+ fun getAllByCountry() {
+ val country = countryRepository.getAll().first()
+ expect(3) { animeRepository.getAllBy("country.tag", country.tag).size }
+ expect(0) { animeRepository.getAllBy("country.tag", "us").size }
+ }
+
+ @Test
+ fun save() {
+ assertThrows {
+ animeRepository.save(
+ Anime(
+ country = Country(tag = "fr", name = "France"),
+ name = "Naruto",
+ image = "hello"
+ )
+ )
+ }
+
+ val anime = Anime(country = Country(tag = "us", name = "United States"), name = "Naruto", image = "hello")
+ animeRepository.save(anime)
+
+ expect(4) { animeRepository.getAll().size }
+ checkNotNull { anime.uuid }
+ expect("Naruto") { anime.name }
+ }
+
+ @Test
+ fun saveAll() {
+ assertThrows {
+ animeRepository.saveAll(
+ listOf(
+ Anime(
+ country = Country(tag = "fr", name = "France"),
+ name = "Naruto",
+ image = "hello"
+ )
+ )
+ )
+ }
+
+ val anime1 = Anime(country = Country(tag = "us", name = "United States"), name = "Naruto", image = "hello")
+ val anime2 = Anime(country = Country(tag = "uk", name = "United Kingdom"), name = "Bleach", image = "hello")
+ animeRepository.saveAll(listOf(anime1, anime2))
+
+ expect(5) { animeRepository.getAll().size }
+ checkNotNull { anime1.uuid }
+ checkNotNull { anime2.uuid }
+ expect("Naruto") { anime1.name }
+ expect("Bleach") { anime2.name }
+ }
+
+ @Test
+ fun delete() {
+ assertThrows {
+ animeRepository.delete(
+ Anime(
+ country = Country(tag = "fr", name = "France"),
+ name = "Naruto",
+ image = "hello"
+ )
+ )
+ }
+
+ val animes = animeRepository.getAll()
+ animeRepository.delete(animes.first())
+ expect(2) { animes.size - 1 }
+ }
+
+ @Test
+ fun deleteAll() {
+ assertThrows {
+ animeRepository.deleteAll(
+ listOf(
+ Anime(
+ country = Country(tag = "fr", name = "France"),
+ name = "Naruto",
+ image = "hello"
+ )
+ )
+ )
+ }
+
+ val animes = animeRepository.getAll()
+ animeRepository.deleteAll(listOf(animes.first(), animes[1]))
+ expect(1) { animes.size - 2 }
+ }
+
+ @Test
+ fun findByHash() {
+ val anime2 = animeRepository.findByHash("fr", "hello")
+ checkNotNull { anime2 }
+ }
+
+ @Test
+ fun findByName() {
+ val animes = animeRepository.findByName("fr", "Naruto")
+ expect(1) { animes.size }
+ }
+
+ @Test
+ fun getByPage() {
+ val simulcast = simulcastRepository.getAll().first()
+
+ val page1 = animeRepository.getByPage("fr", simulcast.uuid, 1, 2)
+ expect(2) { page1.size }
+ val page2 = animeRepository.getByPage("fr", simulcast.uuid, 2, 2)
+ expect(1) { page2.size }
+ }
+
+ @Test
+ fun findByPage() {
+ val animes = animeRepository.getAll()
+ val uuids = listOf(animes[0].uuid, animes[1].uuid, animes[2].uuid)
+
+ val page1 = animeRepository.getByPageWithList(uuids, 1, 2)
+ expect(2) { page1.size }
+ val page2 = animeRepository.getByPageWithList(uuids, 2, 2)
+ expect(1) { page2.size }
+ }
+
+// @Test
+// fun getDiary() {
+// val country = countryRepository.getAll().first()
+// val diary = animeRepository.getDiary(country.tag!!, Calendar.getInstance().get(Calendar.DAY_OF_WEEK))
+// expect(3) { diary.size }
+// }
+}
diff --git a/src/test/kotlin/fr/ziedelth/repositories/CountryRepositoryTest.kt b/src/test/kotlin/fr/ziedelth/repositories/CountryRepositoryTest.kt
new file mode 100644
index 0000000..c9f28a8
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/repositories/CountryRepositoryTest.kt
@@ -0,0 +1,93 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.Country
+import fr.ziedelth.plugins.countryRepository
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertThrows
+import java.util.*
+import kotlin.test.expect
+
+internal class CountryRepositoryTest : AbstractAPITest() {
+ @Test
+ fun find() {
+ val country = countryRepository.find(UUID.randomUUID())
+ expect(null) { country }
+
+ val countries = countryRepository.getAll()
+ expect(countries.first().uuid) { countryRepository.find(countries.first().uuid)?.uuid }
+ }
+
+ @Test
+ fun exists() {
+ expect(true) { countryRepository.exists("tag", "fr") }
+ expect(false) { countryRepository.exists("uuid", UUID.randomUUID()) }
+ }
+
+ @Test
+ fun findAll() {
+ expect(emptyList()) { countryRepository.findAll(listOf(UUID.randomUUID())) }
+
+ val countries = countryRepository.getAll()
+ val list = countryRepository.findAll(listOf(countries[0].uuid, countries[1].uuid))
+
+ expect(true) { list.any { it.uuid == countries.first().uuid } && list.any { it.uuid == countries[1].uuid } }
+ }
+
+ @Test
+ fun getAll() {
+ expect(2) { countryRepository.getAll().size }
+ }
+
+ @Test
+ fun save() {
+ assertThrows {
+ countryRepository.save(Country(tag = "fr", name = "France"))
+ }
+
+ val country = Country(tag = "us", name = "United States")
+ countryRepository.save(country)
+
+ expect(3) { countryRepository.getAll().size }
+ checkNotNull { country.uuid }
+ expect("United States") { country.name }
+ }
+
+ @Test
+ fun saveAll() {
+ assertThrows {
+ countryRepository.saveAll(
+ listOf(
+ Country(tag = "fr", name = "France"),
+ Country(tag = "jp", name = "Japan")
+ )
+ )
+ }
+
+ val country1 = Country(tag = "us", name = "United States")
+ val country2 = Country(tag = "uk", name = "United Kingdom")
+ countryRepository.saveAll(listOf(country1, country2))
+
+ expect(4) { countryRepository.getAll().size }
+ checkNotNull { country1.uuid }
+ checkNotNull { country2.uuid }
+ expect("United States") { country1.name }
+ expect("United Kingdom") { country2.name }
+ }
+
+ @Test
+ fun delete() {
+ assertThrows {
+ countryRepository.delete(
+ Country(
+ tag = "fr",
+ name = "France"
+ )
+ )
+ }
+
+ val countries = countryRepository.getAll()
+ countryRepository.delete(countries.first())
+ expect(1) { countries.size - 1 }
+ }
+}
diff --git a/src/test/kotlin/fr/ziedelth/repositories/EpisodeRepositoryTest.kt b/src/test/kotlin/fr/ziedelth/repositories/EpisodeRepositoryTest.kt
new file mode 100644
index 0000000..42db2b0
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/repositories/EpisodeRepositoryTest.kt
@@ -0,0 +1,37 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.plugins.animeRepository
+import fr.ziedelth.plugins.episodeRepository
+import org.junit.jupiter.api.Test
+import kotlin.test.expect
+
+internal class EpisodeRepositoryTest : AbstractAPITest() {
+ @Test
+ fun getByPage() {
+ val page1 = episodeRepository.getByPage("fr", 1, 2)
+ expect(2) { page1.size }
+ val page2 = episodeRepository.getByPage("fr", 2, 2)
+ expect(2) { page2.size }
+ }
+
+ @Test
+ fun getByPageWithAnime() {
+ val anime = animeRepository.getAll().first()
+
+ val page1 = episodeRepository.getByPageWithAnime(anime.uuid, 1, 2)
+ expect(2) { page1.size }
+ val page2 = episodeRepository.getByPageWithAnime(anime.uuid, 2, 2)
+ expect(2) { page2.size }
+ }
+
+ @Test
+ fun getByPageWithList() {
+ val animes = animeRepository.getAll().take(2).map { it.uuid }
+
+ val page1 = episodeRepository.getByPageWithList(animes, 1, 2)
+ expect(2) { page1.size }
+ val page2 = episodeRepository.getByPageWithList(animes, 2, 2)
+ expect(2) { page2.size }
+ }
+}
diff --git a/src/test/kotlin/fr/ziedelth/repositories/EpisodeTypeRepositoryTest.kt b/src/test/kotlin/fr/ziedelth/repositories/EpisodeTypeRepositoryTest.kt
new file mode 100644
index 0000000..2239926
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/repositories/EpisodeTypeRepositoryTest.kt
@@ -0,0 +1,92 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.EpisodeType
+import fr.ziedelth.plugins.episodeTypeRepository
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertThrows
+import java.util.*
+import kotlin.test.expect
+
+internal class EpisodeTypeRepositoryTest : AbstractAPITest() {
+ @Test
+ fun find() {
+ val episodeType = episodeTypeRepository.find(UUID.randomUUID())
+ expect(null) { episodeType }
+
+ val episodeTypes = episodeTypeRepository.getAll()
+ expect(episodeTypes.first().uuid) { episodeTypeRepository.find(episodeTypes.first().uuid)?.uuid }
+ }
+
+ @Test
+ fun exists() {
+ expect(true) { episodeTypeRepository.exists("name", "Episode") }
+ expect(false) { episodeTypeRepository.exists("uuid", UUID.randomUUID()) }
+ }
+
+ @Test
+ fun findAll() {
+ expect(emptyList()) { episodeTypeRepository.findAll(listOf(UUID.randomUUID())) }
+
+ val episodeTypes = episodeTypeRepository.getAll()
+ val list = episodeTypeRepository.findAll(listOf(episodeTypes[0].uuid, episodeTypes[1].uuid))
+
+ expect(true) { list.any { it.uuid == episodeTypes.first().uuid } && list.any { it.uuid == episodeTypes[1].uuid } }
+ }
+
+ @Test
+ fun getAll() {
+ expect(3) { episodeTypeRepository.getAll().size }
+ }
+
+ @Test
+ fun save() {
+ assertThrows {
+ episodeTypeRepository.save(EpisodeType(name = "Episode"))
+ }
+
+ val episodeType = EpisodeType(name = "Special")
+ episodeTypeRepository.save(episodeType)
+
+ expect(4) { episodeTypeRepository.getAll().size }
+ checkNotNull { episodeType.uuid }
+ expect("Special") { episodeType.name }
+ }
+
+ @Test
+ fun saveAll() {
+ assertThrows {
+ episodeTypeRepository.saveAll(
+ listOf(
+ EpisodeType(name = "Episode"),
+ EpisodeType(name = "OAV")
+ )
+ )
+ }
+
+ val episodeType1 = EpisodeType(name = "Special")
+ val episodeType2 = EpisodeType(name = "Special 2")
+ episodeTypeRepository.saveAll(listOf(episodeType1, episodeType2))
+
+ expect(5) { episodeTypeRepository.getAll().size }
+ checkNotNull { episodeType1.uuid }
+ checkNotNull { episodeType2.uuid }
+ expect("Special") { episodeType1.name }
+ expect("Special 2") { episodeType2.name }
+ }
+
+ @Test
+ fun delete() {
+ assertThrows {
+ episodeTypeRepository.delete(
+ EpisodeType(
+ name = "Episode"
+ )
+ )
+ }
+
+ val episodeTypes = episodeTypeRepository.getAll()
+ episodeTypeRepository.delete(episodeTypes.first())
+ expect(2) { episodeTypes.size - 1 }
+ }
+}
diff --git a/src/test/kotlin/fr/ziedelth/repositories/GenreRepositoryTest.kt b/src/test/kotlin/fr/ziedelth/repositories/GenreRepositoryTest.kt
new file mode 100644
index 0000000..5607f22
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/repositories/GenreRepositoryTest.kt
@@ -0,0 +1,92 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.Genre
+import fr.ziedelth.plugins.genreRepository
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertThrows
+import java.util.*
+import kotlin.test.expect
+
+internal class GenreRepositoryTest : AbstractAPITest() {
+ @Test
+ fun find() {
+ val genre = genreRepository.find(UUID.randomUUID())
+ expect(null) { genre }
+
+ val genres = genreRepository.getAll()
+ expect(genres.first().uuid) { genreRepository.find(genres.first().uuid)?.uuid }
+ }
+
+ @Test
+ fun exists() {
+ expect(true) { genreRepository.exists("name", "Action") }
+ expect(false) { genreRepository.exists("uuid", UUID.randomUUID()) }
+ }
+
+ @Test
+ fun findAll() {
+ expect(emptyList()) { genreRepository.findAll(listOf(UUID.randomUUID())) }
+
+ val genres = genreRepository.getAll()
+ val list = genreRepository.findAll(listOf(genres[0].uuid, genres[1].uuid))
+
+ expect(true) { list.any { it.uuid == genres.first().uuid } && list.any { it.uuid == genres[1].uuid } }
+ }
+
+ @Test
+ fun getAll() {
+ expect(3) { genreRepository.getAll().size }
+ }
+
+ @Test
+ fun save() {
+ assertThrows {
+ genreRepository.save(Genre(name = "Action"))
+ }
+
+ val genre = Genre(name = "Fantasy")
+ genreRepository.save(genre)
+
+ expect(4) { genreRepository.getAll().size }
+ checkNotNull { genre.uuid }
+ expect("Fantasy") { genre.name }
+ }
+
+ @Test
+ fun saveAll() {
+ assertThrows {
+ genreRepository.saveAll(
+ listOf(
+ Genre(name = "Action"),
+ Genre(name = "Drama")
+ )
+ )
+ }
+
+ val genre1 = Genre(name = "Fantasy")
+ val genre2 = Genre(name = "Horror")
+ genreRepository.saveAll(listOf(genre1, genre2))
+
+ expect(5) { genreRepository.getAll().size }
+ checkNotNull { genre1.uuid }
+ checkNotNull { genre2.uuid }
+ expect("Fantasy") { genre1.name }
+ expect("Horror") { genre2.name }
+ }
+
+ @Test
+ fun delete() {
+ assertThrows {
+ genreRepository.delete(
+ Genre(
+ name = "Action"
+ )
+ )
+ }
+
+ val genres = genreRepository.getAll()
+ genreRepository.delete(genres.first())
+ expect(2) { genres.size - 1 }
+ }
+}
diff --git a/src/test/kotlin/fr/ziedelth/repositories/LangTypeRepositoryTest.kt b/src/test/kotlin/fr/ziedelth/repositories/LangTypeRepositoryTest.kt
new file mode 100644
index 0000000..c972734
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/repositories/LangTypeRepositoryTest.kt
@@ -0,0 +1,92 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.LangType
+import fr.ziedelth.plugins.langTypeRepository
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertThrows
+import java.util.*
+import kotlin.test.expect
+
+internal class LangTypeRepositoryTest : AbstractAPITest() {
+ @Test
+ fun find() {
+ val langType = langTypeRepository.find(UUID.randomUUID())
+ expect(null) { langType }
+
+ val langTypes = langTypeRepository.getAll()
+ expect(langTypes.first().uuid) { langTypeRepository.find(langTypes.first().uuid)?.uuid }
+ }
+
+ @Test
+ fun exists() {
+ expect(true) { langTypeRepository.exists("name", "SUBTITLES") }
+ expect(false) { langTypeRepository.exists("uuid", UUID.randomUUID()) }
+ }
+
+ @Test
+ fun findAll() {
+ expect(emptyList()) { langTypeRepository.findAll(listOf(UUID.randomUUID())) }
+
+ val langTypes = langTypeRepository.getAll()
+ val list = langTypeRepository.findAll(listOf(langTypes[0].uuid, langTypes[1].uuid))
+
+ expect(true) { list.any { it.uuid == langTypes.first().uuid } && list.any { it.uuid == langTypes[1].uuid } }
+ }
+
+ @Test
+ fun getAll() {
+ expect(2) { langTypeRepository.getAll().size }
+ }
+
+ @Test
+ fun save() {
+ assertThrows {
+ langTypeRepository.save(LangType(name = "SUBTITLES"))
+ }
+
+ val langType = LangType(name = "DUB")
+ langTypeRepository.save(langType)
+
+ expect(3) { langTypeRepository.getAll().size }
+ checkNotNull { langType.uuid }
+ expect("DUB") { langType.name }
+ }
+
+ @Test
+ fun saveAll() {
+ assertThrows {
+ langTypeRepository.saveAll(
+ listOf(
+ LangType(name = "SUBTITLES"),
+ LangType(name = "VOICE")
+ )
+ )
+ }
+
+ val langType1 = LangType(name = "DUB")
+ val langType2 = LangType(name = "DUB2")
+ langTypeRepository.saveAll(listOf(langType1, langType2))
+
+ expect(4) { langTypeRepository.getAll().size }
+ checkNotNull { langType1.uuid }
+ checkNotNull { langType2.uuid }
+ expect("DUB") { langType1.name }
+ expect("DUB2") { langType2.name }
+ }
+
+ @Test
+ fun delete() {
+ assertThrows {
+ langTypeRepository.delete(
+ LangType(
+ name = "SUBTITLES"
+ )
+ )
+ }
+
+ val langTypes = langTypeRepository.getAll()
+ langTypeRepository.delete(langTypes.first())
+ expect(1) { langTypes.size - 1 }
+ }
+}
diff --git a/src/test/kotlin/fr/ziedelth/repositories/MangaRepositoryTest.kt b/src/test/kotlin/fr/ziedelth/repositories/MangaRepositoryTest.kt
new file mode 100644
index 0000000..c86cf0c
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/repositories/MangaRepositoryTest.kt
@@ -0,0 +1,37 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.plugins.animeRepository
+import fr.ziedelth.plugins.mangaRepository
+import org.junit.jupiter.api.Test
+import kotlin.test.expect
+
+internal class MangaRepositoryTest : AbstractAPITest() {
+ @Test
+ fun getByPage() {
+ val page1 = mangaRepository.getByPage("fr", 1, 2)
+ expect(2) { page1.size }
+ val page2 = mangaRepository.getByPage("fr", 2, 2)
+ expect(2) { page2.size }
+ }
+
+ @Test
+ fun getByPageWithAnime() {
+ val anime = animeRepository.getAll().first()
+
+ val page1 = mangaRepository.getByPageWithAnime(anime.uuid, 1, 2)
+ expect(2) { page1.size }
+ val page2 = mangaRepository.getByPageWithAnime(anime.uuid, 2, 2)
+ expect(2) { page2.size }
+ }
+
+ @Test
+ fun getByPageWithList() {
+ val mangas = mangaRepository.getAll().take(3).map { it.uuid }
+
+ val page1 = mangaRepository.getByPageWithList(mangas, 1, 2)
+ expect(2) { page1.size }
+ val page2 = mangaRepository.getByPageWithList(mangas, 2, 2)
+ expect(1) { page2.size }
+ }
+}
diff --git a/src/test/kotlin/fr/ziedelth/repositories/NewsRepositoryTest.kt b/src/test/kotlin/fr/ziedelth/repositories/NewsRepositoryTest.kt
new file mode 100644
index 0000000..5abb952
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/repositories/NewsRepositoryTest.kt
@@ -0,0 +1,16 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.plugins.newsRepository
+import org.junit.jupiter.api.Test
+import kotlin.test.expect
+
+internal class NewsRepositoryTest : AbstractAPITest() {
+ @Test
+ fun getByPage() {
+ val page1 = newsRepository.getByPage("fr", 1, 2)
+ expect(2) { page1.size }
+ val page2 = newsRepository.getByPage("fr", 2, 2)
+ expect(0) { page2.size }
+ }
+}
diff --git a/src/test/kotlin/fr/ziedelth/repositories/PlatformRepositoryTest.kt b/src/test/kotlin/fr/ziedelth/repositories/PlatformRepositoryTest.kt
new file mode 100644
index 0000000..b987714
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/repositories/PlatformRepositoryTest.kt
@@ -0,0 +1,108 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.Platform
+import fr.ziedelth.plugins.platformRepository
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertThrows
+import java.util.*
+import kotlin.test.expect
+
+internal class PlatformRepositoryTest : AbstractAPITest() {
+ @Test
+ fun find() {
+ val platform = platformRepository.find(UUID.randomUUID())
+ expect(null) { platform }
+
+ val platforms = platformRepository.getAll()
+ expect(platforms.first().uuid) { platformRepository.find(platforms.first().uuid)?.uuid }
+ }
+
+ @Test
+ fun exists() {
+ expect(true) { platformRepository.exists("name", "Netflix") }
+ expect(false) { platformRepository.exists("uuid", UUID.randomUUID()) }
+ }
+
+ @Test
+ fun findAll() {
+ expect(emptyList()) { platformRepository.findAll(listOf(UUID.randomUUID())) }
+
+ val platforms = platformRepository.getAll()
+ val list = platformRepository.findAll(listOf(platforms[0].uuid, platforms[1].uuid))
+
+ expect(true) { list.any { it.uuid == platforms.first().uuid } && list.any { it.uuid == platforms[1].uuid } }
+ }
+
+ @Test
+ fun getAll() {
+ expect(3) { platformRepository.getAll().size }
+ }
+
+ @Test
+ fun save() {
+ assertThrows {
+ platformRepository.save(
+ Platform(
+ name = "Netflix",
+ image = "hello",
+ url = "hello"
+ )
+ )
+ }
+
+ val platform = Platform(name = "Animation Digital Network", image = "hello", url = "hello")
+ platformRepository.save(platform)
+
+ expect(4) { platformRepository.getAll().size }
+ checkNotNull { platform.uuid }
+ expect("Animation Digital Network") { platform.name }
+ }
+
+ @Test
+ fun saveAll() {
+ assertThrows {
+ platformRepository.saveAll(
+ listOf(
+ Platform(
+ name = "Netflix",
+ image = "hello",
+ url = "hello"
+ ),
+ Platform(
+ name = "Crunchyroll",
+ image = "hello",
+ url = "hello"
+ )
+ )
+ )
+ }
+
+ val platform1 = Platform(name = "Animation Digital Network", image = "hello", url = "hello")
+ val platform2 = Platform(name = "MangaNews", image = "hello", url = "hello")
+ platformRepository.saveAll(listOf(platform1, platform2))
+
+ expect(5) { platformRepository.getAll().size }
+ checkNotNull { platform1.uuid }
+ checkNotNull { platform2.uuid }
+ expect("Animation Digital Network") { platform1.name }
+ expect("MangaNews") { platform2.name }
+ }
+
+ @Test
+ fun delete() {
+ assertThrows {
+ platformRepository.delete(
+ Platform(
+ name = "Netflix",
+ image = "hello",
+ url = "hello"
+ )
+ )
+ }
+
+ val platforms = platformRepository.getAll()
+ platformRepository.delete(platforms.first())
+ expect(2) { platforms.size - 1 }
+ }
+}
diff --git a/src/test/kotlin/fr/ziedelth/repositories/SimulcastRepositoryTest.kt b/src/test/kotlin/fr/ziedelth/repositories/SimulcastRepositoryTest.kt
new file mode 100644
index 0000000..8d6d7f0
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/repositories/SimulcastRepositoryTest.kt
@@ -0,0 +1,109 @@
+package fr.ziedelth.repositories
+
+import fr.ziedelth.AbstractAPITest
+import fr.ziedelth.entities.Simulcast
+import fr.ziedelth.plugins.countryRepository
+import fr.ziedelth.plugins.simulcastRepository
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertThrows
+import java.util.*
+import kotlin.test.expect
+
+internal class SimulcastRepositoryTest : AbstractAPITest() {
+ @Test
+ fun find() {
+ val simulcast = simulcastRepository.find(UUID.randomUUID())
+ expect(null) { simulcast }
+
+ val simulcasts = simulcastRepository.getAll()
+ expect(simulcasts.first().uuid) { simulcastRepository.find(simulcasts.first().uuid)?.uuid }
+ }
+
+ @Test
+ fun exists() {
+ expect(true) { simulcastRepository.exists("year", 2020) }
+ expect(false) { simulcastRepository.exists("uuid", UUID.randomUUID()) }
+ }
+
+ @Test
+ fun findAll() {
+ expect(emptyList()) { simulcastRepository.findAll(listOf(UUID.randomUUID())) }
+
+ val simulcasts = simulcastRepository.getAll()
+ val list = simulcastRepository.findAll(listOf(simulcasts[0].uuid, simulcasts[1].uuid))
+
+ expect(true) { list.any { it.uuid == simulcasts.first().uuid } && list.any { it.uuid == simulcasts[1].uuid } }
+ }
+
+ @Test
+ fun getAll() {
+ expect(2) { simulcastRepository.getAll().size }
+ }
+
+ @Test
+ fun save() {
+ assertThrows {
+ simulcastRepository.save(Simulcast(year = 2020, season = "WINTER"))
+ }
+
+ val simulcast = Simulcast.getSimulcast(2021, 1)
+ simulcastRepository.save(simulcast)
+
+ expect(3) { simulcastRepository.getAll().size }
+ checkNotNull { simulcast.uuid }
+ expect("WINTER") { simulcast.season }
+ }
+
+ @Test
+ fun saveAll() {
+ assertThrows {
+ simulcastRepository.saveAll(
+ listOf(
+ Simulcast(year = 2020, season = "WINTER"),
+ Simulcast(year = 2020, season = "SPRING")
+ )
+ )
+ }
+
+ val simulcast1 = Simulcast.getSimulcast(2019, 1)
+ val simulcast2 = Simulcast.getSimulcast(2019, 11)
+ simulcastRepository.saveAll(listOf(simulcast1, simulcast2))
+
+ expect(4) { simulcastRepository.getAll().size }
+ checkNotNull { simulcast1.uuid }
+ checkNotNull { simulcast2.uuid }
+ expect("WINTER") { simulcast1.season }
+ expect("AUTUMN") { simulcast2.season }
+ }
+
+ @Test
+ fun delete() {
+ assertThrows {
+ simulcastRepository.delete(
+ Simulcast(
+ UUID.randomUUID(),
+ season = "WINTER",
+ year = 2020
+ )
+ )
+ }
+
+ val simulcasts = simulcastRepository.getAll()
+ simulcastRepository.delete(simulcasts.first())
+ expect(1) { simulcasts.size - 1 }
+ }
+
+ @Test
+ fun getAllByTag() {
+ val country = countryRepository.getAll().first()
+ val simulcasts = simulcastRepository.getAll(country.tag)
+ expect(1) { simulcasts.size }
+ expect("WINTER") { simulcasts.first().season }
+ }
+
+ @Test
+ fun findBySeasonAndYear() {
+ val simulcast = simulcastRepository.findBySeasonAndYear("WINTER", 2020)
+ checkNotNull(simulcast?.uuid)
+ }
+}
diff --git a/src/test/kotlin/fr/ziedelth/utils/DatabaseTest.kt b/src/test/kotlin/fr/ziedelth/utils/DatabaseTest.kt
new file mode 100644
index 0000000..0ed51c7
--- /dev/null
+++ b/src/test/kotlin/fr/ziedelth/utils/DatabaseTest.kt
@@ -0,0 +1,55 @@
+package fr.ziedelth.utils
+
+import org.hibernate.Session
+import org.hibernate.SessionFactory
+import org.hibernate.boot.registry.StandardServiceRegistryBuilder
+import org.hibernate.cfg.Configuration
+import org.reflections.Reflections
+import java.io.File
+import java.io.Serializable
+import kotlin.system.exitProcess
+
+object DatabaseTest {
+ private var sessionFactory: SessionFactory
+
+ init {
+ try {
+ val file = File(
+ javaClass.classLoader.getResource("hibernate.cfg.xml")?.file
+ ?: throw Exception("hibernate.cfg.xml not found")
+ )
+
+ Configuration().let { configuration ->
+ getEntities().forEach { configuration.addAnnotatedClass(it) }
+
+ configuration.configure(file)
+ sessionFactory = configuration.buildSessionFactory(
+ StandardServiceRegistryBuilder().applySettings(configuration.properties).build()
+ )
+ }
+ } catch (e: Exception) {
+ e.printStackTrace()
+ exitProcess(1)
+ }
+ }
+
+ private fun getEntities(): MutableSet> =
+ Reflections("fr.ziedelth.entities").getSubTypesOf(Serializable::class.java)
+
+ fun getSession(): Session = sessionFactory.openSession()
+
+ fun clean() {
+ val session = getSession()
+ val transaction = session.beginTransaction()
+
+ try {
+ getEntities().forEach { session.createQuery("DELETE FROM ${it.simpleName}").executeUpdate() }
+ transaction.commit()
+ } catch (e: Exception) {
+ transaction.rollback()
+ throw e
+ } finally {
+ session.close()
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/fr/ziedelth/PluginManagerTest.kt b/src/test/kotlin/fr/ziedelth/utils/plugins/PluginManagerTest.kt
similarity index 91%
rename from src/test/kotlin/fr/ziedelth/PluginManagerTest.kt
rename to src/test/kotlin/fr/ziedelth/utils/plugins/PluginManagerTest.kt
index 50deb94..a1ed971 100644
--- a/src/test/kotlin/fr/ziedelth/PluginManagerTest.kt
+++ b/src/test/kotlin/fr/ziedelth/utils/plugins/PluginManagerTest.kt
@@ -1,7 +1,6 @@
-package fr.ziedelth
+package fr.ziedelth.utils.plugins
import fr.ziedelth.events.ExampleEvent
-import fr.ziedelth.utils.plugins.PluginManager
import fr.ziedelth.utils.plugins.events.EventHandler
import fr.ziedelth.utils.plugins.events.Listener
import org.junit.jupiter.api.Assertions.assertEquals
diff --git a/src/test/resources/hibernate.cfg.xml b/src/test/resources/hibernate.cfg.xml
new file mode 100644
index 0000000..7522471
--- /dev/null
+++ b/src/test/resources/hibernate.cfg.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ org.h2.Driver
+ jdbc:h2:mem:test;DATABASE_TO_UPPER=false
+
+
+ org.hibernate.dialect.H2Dialect
+ false
+ create-drop
+
+
\ No newline at end of file