Skip to content

Commit

Permalink
Reduce code smells
Browse files Browse the repository at this point in the history
  • Loading branch information
Ziedelth committed Feb 14, 2024
1 parent a2007fe commit c34f0b6
Show file tree
Hide file tree
Showing 47 changed files with 458 additions and 342 deletions.
59 changes: 39 additions & 20 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,29 @@ import java.net.URI

val ktorVersion = "2.3.8"
val kotlinVersion = "1.9.22"
val ktorSwaggerUiVersion = "2.7.4"
val hibernateCoreVersion = "6.4.4.Final"
val hibernateSearchVersion = "7.1.0.CR1"
val junitVersion = "5.10.2"
val tikaVersion = "3.0.0-BETA"
val ktorSwaggerUiVersion = "2.7.4"
val postgresqlVersion = "42.7.0"
val reflectionsVersion = "0.10.2"
val guiceVersion = "7.0.0"
val liquibaseCoreVersion = "4.26.0"
val quartzVersion = "2.5.0-rc1"
val guavaVersion = "33.0.0-jre"
val jacksonVersion = "2.16.1"
val playwrightVersion = "1.41.2"
val jsoupVersion = "1.17.2"
val gsonVersion = "2.10.1"
val openCvVersion = "4.9.0-0"
val bcprovVersion = "1.77"
val javaImageScalingVersion = "0.8.6"
val jdaVersion = "5.0.0-beta.20"
val twitter4jVersion = "4.0.7"
val twitter4jV2Version = "1.4.3"

val junitVersion = "5.10.2"
val h2Version = "2.2.224"

plugins {
kotlin("jvm") version "1.9.22"
Expand Down Expand Up @@ -48,35 +67,35 @@ dependencies {
implementation("io.ktor:ktor-client-okhttp:$ktorVersion")
implementation("io.ktor:ktor-client-okhttp-jvm:$ktorVersion")
implementation("io.github.smiley4:ktor-swagger-ui:$ktorSwaggerUiVersion")
implementation("org.hibernate.orm:hibernate-core:6.4.4.Final")
implementation("org.hibernate.orm:hibernate-core:$hibernateCoreVersion")
implementation("org.hibernate.search:hibernate-search-mapper-orm:$hibernateSearchVersion")
implementation("org.hibernate.search:hibernate-search-backend-lucene:$hibernateSearchVersion")
implementation("org.postgresql:postgresql:42.7.0")
implementation("org.reflections:reflections:0.10.2")
implementation("com.google.inject:guice:7.0.0")
implementation("org.liquibase:liquibase-core:4.26.0")
implementation("org.quartz-scheduler:quartz:2.5.0-rc1")
implementation("com.google.guava:guava:33.0.0-jre")
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.16.1")
implementation("com.microsoft.playwright:playwright:1.41.2")
implementation("org.jsoup:jsoup:1.17.2")
implementation("com.google.code.gson:gson:2.10.1")
implementation("org.openpnp:opencv:4.9.0-0")
implementation("org.bouncycastle:bcprov-jdk18on:1.77")
implementation("com.mortennobel:java-image-scaling:0.8.6")
implementation("org.postgresql:postgresql:$postgresqlVersion")
implementation("org.reflections:reflections:$reflectionsVersion")
implementation("com.google.inject:guice:$guiceVersion")
implementation("org.liquibase:liquibase-core:$liquibaseCoreVersion")
implementation("org.quartz-scheduler:quartz:$quartzVersion")
implementation("com.google.guava:guava:$guavaVersion")
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:$jacksonVersion")
implementation("com.microsoft.playwright:playwright:$playwrightVersion")
implementation("org.jsoup:jsoup:$jsoupVersion")
implementation("com.google.code.gson:gson:$gsonVersion")
implementation("org.openpnp:opencv:$openCvVersion")
implementation("org.bouncycastle:bcprov-jdk18on:$bcprovVersion")
implementation("com.mortennobel:java-image-scaling:$javaImageScalingVersion")
implementation("org.apache.tika:tika-core:$tikaVersion")
implementation("org.apache.tika:tika-langdetect-optimaize:$tikaVersion")

// Social networks
implementation("com.github.discord-jda:JDA:v5.0.0-beta.20")
implementation("org.twitter4j:twitter4j-core:4.0.7")
implementation("io.github.takke:jp.takke.twitter4j-v2:1.4.3")
implementation("com.github.discord-jda:JDA:$jdaVersion")
implementation("org.twitter4j:twitter4j-core:$twitter4jVersion")
implementation("io.github.takke:jp.takke.twitter4j-v2:$twitter4jV2Version")

testImplementation("io.ktor:ktor-server-tests-jvm:$ktorVersion")
testImplementation("io.ktor:ktor-client-mock:$ktorVersion")
testImplementation("org.junit.jupiter:junit-jupiter-api:$junitVersion")
testImplementation("org.junit.jupiter:junit-jupiter-engine:$junitVersion")
testImplementation("com.h2database:h2:2.2.224")
testImplementation("com.h2database:h2:$h2Version")
}

kotlin {
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/fr/shikkanime/Application.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fun main() {
JobManager.scheduleJob("0 0 * * * ?", SavingImageCacheJob::class.java)
JobManager.scheduleJob("0 */10 * * * ?", GarbageCollectorJob::class.java)
JobManager.scheduleJob("0 0 0 * * ?", DeleteOldMetricsJob::class.java)
JobManager.scheduleJob("0 0 * * * ?", FetchOldEpisodeDescriptionJob::class.java)
JobManager.scheduleJob("0 0 * * * ?", FetchDeprecatedEpisodeJob::class.java)

Check warning on line 52 in src/main/kotlin/fr/shikkanime/Application.kt

View check run for this annotation

Codecov / codecov/patch

src/main/kotlin/fr/shikkanime/Application.kt#L52

Added line #L52 was not covered by tests
JobManager.start()

logger.info("Starting server...")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class AdminPlatformController {
?: abstractPlatform.configuration!!.newPlatformSimulcast()
simulcast.of(parameters)

if (uuid == null) {
if (simulcast.uuid == null) {
simulcast.uuid = UUID.randomUUID()
abstractPlatform.configuration?.addPlatformSimulcast(simulcast)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class SiteController {
@Get
private fun catalogSimulcast(@PathParam("slug") slug: String): Response {
val findAll = simulcastCacheService.findAll()!!
val currentSimulcast = findAll.first { it.slug == slug }
val currentSimulcast = findAll.firstOrNull { it.slug == slug } ?: return Response.redirect("/404")

return Response.template(
Link.CATALOG.template,
Expand All @@ -138,6 +138,7 @@ class SiteController {
@Get
private fun error404(): Response {
return Response.template(
HttpStatusCode.NotFound,

Check warning on line 141 in src/main/kotlin/fr/shikkanime/controllers/site/SiteController.kt

View check run for this annotation

Codecov / codecov/patch

src/main/kotlin/fr/shikkanime/controllers/site/SiteController.kt#L141

Added line #L141 was not covered by tests
"/site/404.ftl",
"Page introuvable"
)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class EpisodeToEpisodeDtoConverter : AbstractConverter<Episode, EpisodeDto>() {
duration = from.duration,
description = from.description,
uncensored = from.image!!.contains("nc/", true),
lastUpdateDateTime = from.lastUpdateDateTime?.withUTC()?.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
)
}
}
1 change: 1 addition & 0 deletions src/main/kotlin/fr/shikkanime/dtos/EpisodeDto.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ data class EpisodeDto(
val duration: Long,
val description: String?,
val uncensored: Boolean,
val lastUpdateDateTime: String?,
) : Serializable
2 changes: 2 additions & 0 deletions src/main/kotlin/fr/shikkanime/entities/Episode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,6 @@ data class Episode(
var duration: Long = -1,
@Column(nullable = true, columnDefinition = "VARCHAR(1000)")
var description: String? = null,
@Column(nullable = true, name = "last_update_date_time")
var lastUpdateDateTime: ZonedDateTime? = releaseDateTime,
) : ShikkEntity(uuid)
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ enum class ConfigPropertyKey(val key: String) {
SOCIAL_NETWORK_EPISODES_SIZE_LIMIT("social_network_episodes_size_limit"),
FETCH_OLD_EPISODE_DESCRIPTION_SIZE("fetch_old_episode_description_size"),
GOOGLE_SITE_VERIFICATION_ID("google_site_verification_id"),
FETCH_DEPRECATED_EPISODE_DATE("fetch_deprecated_episode_date"),
}
4 changes: 2 additions & 2 deletions src/main/kotlin/fr/shikkanime/jobs/AbstractJob.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package fr.shikkanime.jobs

abstract class AbstractJob {
abstract fun run()
fun interface AbstractJob {
fun run()
}
2 changes: 1 addition & 1 deletion src/main/kotlin/fr/shikkanime/jobs/DeleteOldMetricsJob.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.google.inject.Inject
import fr.shikkanime.services.MetricService
import java.time.ZonedDateTime

class DeleteOldMetricsJob : AbstractJob() {
class DeleteOldMetricsJob : AbstractJob {
@Inject
private lateinit var metricService: MetricService

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,22 @@ import com.google.inject.Inject
import fr.shikkanime.entities.Episode
import fr.shikkanime.entities.enums.ConfigPropertyKey
import fr.shikkanime.entities.enums.CountryCode
import fr.shikkanime.entities.enums.EpisodeType
import fr.shikkanime.entities.enums.Platform
import fr.shikkanime.services.EpisodeService
import fr.shikkanime.services.caches.ConfigCacheService
import fr.shikkanime.utils.HttpRequest
import fr.shikkanime.utils.LoggerFactory
import fr.shikkanime.utils.MapCache
import fr.shikkanime.utils.ObjectParser.getAsInt
import fr.shikkanime.utils.ObjectParser.getAsString
import fr.shikkanime.utils.withUTC
import fr.shikkanime.wrappers.AnimationDigitalNetworkWrapper
import fr.shikkanime.wrappers.CrunchyrollWrapper
import kotlinx.coroutines.runBlocking
import java.time.ZonedDateTime
import java.util.logging.Level

class FetchOldEpisodeDescriptionJob : AbstractJob() {
class FetchDeprecatedEpisodeJob : AbstractJob {
private val logger = LoggerFactory.getLogger(javaClass)

@Inject
Expand All @@ -31,27 +33,42 @@ class FetchOldEpisodeDescriptionJob : AbstractJob() {
val httpRequest = HttpRequest()
val anonymousAccessToken = runBlocking { CrunchyrollWrapper.getAnonymousAccessToken() }
val cms = runBlocking { CrunchyrollWrapper.getCMS(anonymousAccessToken) }

val takeSize = configCacheService.getValueAsInt(ConfigPropertyKey.FETCH_OLD_EPISODE_DESCRIPTION_SIZE, 0)

val crunchyrollEpisodes = episodeService.findAllByPlatform(Platform.CRUN)
val adnEpisodes = episodeService.findAllByPlatform(Platform.ANIM)
val now = ZonedDateTime.now().withSecond(0).withNano(0).withUTC()
val deprecatedDateTime = now.minusDays(

Check warning on line 40 in src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt

View check run for this annotation

Codecov / codecov/patch

src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt#L39-L40

Added lines #L39 - L40 were not covered by tests
configCacheService.getValueAsInt(ConfigPropertyKey.FETCH_DEPRECATED_EPISODE_DATE, 30).toLong()
)

val crunchyrollEpisodes = episodeService.findAllByPlatformDeprecatedEpisodes(Platform.CRUN, deprecatedDateTime)
val adnEpisodes = episodeService.findAllByPlatformDeprecatedEpisodes(Platform.ANIM, deprecatedDateTime)

val episodes = (crunchyrollEpisodes + adnEpisodes)
.filter { it.description.isNullOrBlank() }
.shuffled()
.take(takeSize)

logger.info("Found ${episodes.size} episodes")

episodes.forEachIndexed { index, episode ->
logger.info("Fetching episode description ${index + 1}/${episodes.size}")
val s = "${episode.anime?.name} - S${episode.season} EP${episode.number}"

val s = "${episode.anime?.name} - S${episode.season} ${
when (episode.episodeType!!) {
EpisodeType.EPISODE -> "EP"
EpisodeType.SPECIAL -> "SP"
EpisodeType.FILM -> "MOV"

Check warning on line 60 in src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt

View check run for this annotation

Codecov / codecov/patch

src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt#L58-L60

Added lines #L58 - L60 were not covered by tests
}
}${episode.number}"

Check warning on line 62 in src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt

View check run for this annotation

Codecov / codecov/patch

src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt#L62

Added line #L62 was not covered by tests

try {
val content = runBlocking { normalizeContent(episode, httpRequest, anonymousAccessToken, cms) } ?: return@forEachIndexed
val description = normalizeDescription(episode, content)
logger.config("$s : $description")
val title = normalizeTitle(episode.platform!!, content)
val description = normalizeDescription(episode.platform!!, content)
logger.config("$s : $title - $description")
episode.title = title

Check warning on line 69 in src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt

View check run for this annotation

Codecov / codecov/patch

src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt#L66-L69

Added lines #L66 - L69 were not covered by tests
episode.description = description
episode.lastUpdateDateTime = now

Check warning on line 71 in src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt

View check run for this annotation

Codecov / codecov/patch

src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt#L71

Added line #L71 was not covered by tests
episodeService.update(episode)
} catch (e: Exception) {
logger.log(Level.SEVERE, "Error while fetching episode description for $s", e)
Expand All @@ -65,7 +82,7 @@ class FetchOldEpisodeDescriptionJob : AbstractJob() {
httpRequest.close()
}

fun normalizeUrl(platform: Platform, countryCode: CountryCode, url: String): String {
private fun normalizeUrl(platform: Platform, countryCode: CountryCode, url: String): String {
return when (platform) {
Platform.CRUN -> {
val other = "https://www.crunchyroll.com/${countryCode.name.lowercase()}/"
Expand All @@ -91,18 +108,28 @@ class FetchOldEpisodeDescriptionJob : AbstractJob() {

else -> {
val split = episode.url!!.split("/")
val animeNameEncoded = split[split.size - 2]
val animeId = AnimationDigitalNetworkWrapper.getShow(animeNameEncoded).getAsInt("id")!!
val videoId = split[split.size - 1].split("-")[0].toInt()
AnimationDigitalNetworkWrapper.getShowVideos(animeId, videoId)[0]
AnimationDigitalNetworkWrapper.getShowVideo(videoId)

Check warning on line 112 in src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt

View check run for this annotation

Codecov / codecov/patch

src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt#L112

Added line #L112 was not covered by tests
}
}
}

fun normalizeUrl(url: String) = "/watch/([A-Z0-9]+)".toRegex().find(url)!!.groupValues[1]

private fun normalizeDescription(episode: Episode, content: JsonObject): String? {
var description = when (episode.platform) {
private fun normalizeTitle(platform: Platform, content: JsonObject): String? {
var title = when (platform) {

Check warning on line 120 in src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt

View check run for this annotation

Codecov / codecov/patch

src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt#L120

Added line #L120 was not covered by tests
Platform.CRUN -> content.getAsString("title")
else -> content.getAsString("name")

Check warning on line 122 in src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt

View check run for this annotation

Codecov / codecov/patch

src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt#L122

Added line #L122 was not covered by tests
}

title = title?.replace("\n", "")
title = title?.replace("\r", "")
title = title?.trim()
return title

Check warning on line 128 in src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt

View check run for this annotation

Codecov / codecov/patch

src/main/kotlin/fr/shikkanime/jobs/FetchDeprecatedEpisodeJob.kt#L128

Added line #L128 was not covered by tests
}

fun normalizeDescription(platform: Platform, content: JsonObject): String? {
var description = when (platform) {
Platform.CRUN -> content.getAsString("description")
else -> content.getAsString("summary")
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/fr/shikkanime/jobs/FetchEpisodesJob.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import java.time.ZonedDateTime
import java.util.logging.Level


class FetchEpisodesJob : AbstractJob() {
class FetchEpisodesJob : AbstractJob {
private val logger = LoggerFactory.getLogger(javaClass)
private var isInitialized = false
private var isRunning = false
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/fr/shikkanime/jobs/GarbageCollectorJob.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package fr.shikkanime.jobs

class GarbageCollectorJob : AbstractJob() {
class GarbageCollectorJob : AbstractJob {
override fun run() {
System.gc()
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/fr/shikkanime/jobs/MetricJob.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import java.lang.management.ManagementFactory
import javax.management.Attribute
import javax.management.ObjectName

class MetricJob : AbstractJob() {
class MetricJob : AbstractJob {
@Inject
private lateinit var metricService: MetricService

Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/fr/shikkanime/jobs/SavingImageCacheJob.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package fr.shikkanime.jobs

import fr.shikkanime.services.ImageService

class SavingImageCacheJob : AbstractJob() {
class SavingImageCacheJob : AbstractJob {
override fun run() {
ImageService.saveCache()
}
Expand Down
9 changes: 1 addition & 8 deletions src/main/kotlin/fr/shikkanime/platforms/AbstractPlatform.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import fr.shikkanime.utils.ObjectParser
import fr.shikkanime.utils.isEqualOrAfter
import kotlinx.coroutines.runBlocking
import java.io.File
import java.lang.reflect.ParameterizedType
import java.time.ZonedDateTime
import java.util.logging.Level

Expand All @@ -20,6 +19,7 @@ abstract class AbstractPlatform<C : PlatformConfiguration<*>, K : Any, V> {
private var apiCache = mutableMapOf<Pair<K, ZonedDateTime>, V>()

abstract fun getPlatform(): Platform
abstract fun getConfigurationClass(): Class<C>
abstract suspend fun fetchApiContent(key: K, zonedDateTime: ZonedDateTime): V
abstract fun fetchEpisodes(zonedDateTime: ZonedDateTime, bypassFileContent: File? = null): List<Episode>

Expand Down Expand Up @@ -68,11 +68,4 @@ abstract class AbstractPlatform<C : PlatformConfiguration<*>, K : Any, V> {
if (!folder.exists()) folder.mkdirs()
return File(folder, "${getPlatform().platformName.lowercase().replace(" ", "-")}.json")
}

private fun getConfigurationClass(): Class<C> {
val type = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0]
require(type is Class<*>) { "Configuration class must be a class" }
@Suppress("UNCHECKED_CAST")
return type as Class<C>
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class AnimationDigitalNetworkPlatform :
AbstractPlatform<AnimationDigitalNetworkConfiguration, CountryCode, List<JsonObject>>() {
override fun getPlatform(): Platform = Platform.ANIM

override fun getConfigurationClass() = AnimationDigitalNetworkConfiguration::class.java

override suspend fun fetchApiContent(key: CountryCode, zonedDateTime: ZonedDateTime): List<JsonObject> {
return AnimationDigitalNetworkWrapper.getLatestVideos(zonedDateTime.toLocalDate())
}
Expand Down
Loading

0 comments on commit c34f0b6

Please sign in to comment.