Skip to content

Commit

Permalink
Add DiscordService
Browse files Browse the repository at this point in the history
  • Loading branch information
Ziedelth committed Jan 9, 2024
1 parent 218eacd commit c4644d8
Show file tree
Hide file tree
Showing 12 changed files with 129 additions and 16 deletions.
4 changes: 4 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import java.net.URI

val ktor_version: String by project
val kotlin_version: String by project

Expand All @@ -19,6 +21,7 @@ application {

repositories {
mavenCentral()
maven { url = URI("https://jitpack.io") }
}

dependencies {
Expand Down Expand Up @@ -58,6 +61,7 @@ dependencies {
implementation("com.mortennobel:java-image-scaling:0.8.6")
implementation("org.apache.tika:tika-core:3.0.0-BETA")
implementation("org.apache.tika:tika-langdetect-optimaize:3.0.0-BETA")
implementation("com.github.discord-jda:JDA:v5.0.0-beta.19")
testImplementation("io.ktor:ktor-server-tests-jvm:$ktor_version")
testImplementation("io.ktor:ktor-client-mock:$ktor_version")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
Expand Down
11 changes: 5 additions & 6 deletions src/main/kotlin/fr/shikkanime/Application.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ import fr.shikkanime.jobs.*
import fr.shikkanime.plugins.configureHTTP
import fr.shikkanime.plugins.configureRouting
import fr.shikkanime.plugins.configureSecurity
import fr.shikkanime.services.AnimeService
import fr.shikkanime.services.EpisodeService
import fr.shikkanime.services.ImageService
import fr.shikkanime.services.MemberService
import fr.shikkanime.services.*
import fr.shikkanime.utils.*
import io.ktor.client.statement.*
import io.ktor.http.*
Expand All @@ -25,14 +22,16 @@ fun main() {
logger.info("Starting ShikkAnime...")
ImageService.loadCache()

val memberService = Constant.injector.getInstance(MemberService::class.java)
val animeService = Constant.injector.getInstance(AnimeService::class.java)
val episodeService = Constant.injector.getInstance(EpisodeService::class.java)
val discordService = Constant.injector.getInstance(DiscordService::class.java)

memberService.initDefaultAdminUser()
animeService.preIndex()
animeService.findAll().forEach { animeService.addImage(it) }
episodeService.findAll().forEach { episodeService.addImage(it) }

Constant.injector.getInstance(MemberService::class.java).initDefaultAdminUser()
discordService.init()

// Sync episodes from Jais
if (false) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import fr.shikkanime.converters.AbstractConverter
import fr.shikkanime.dtos.ConfigDto
import fr.shikkanime.entities.enums.Link
import fr.shikkanime.services.ConfigService
import fr.shikkanime.services.DiscordService
import fr.shikkanime.utils.routes.AdminSessionAuthenticated
import fr.shikkanime.utils.routes.Controller
import fr.shikkanime.utils.routes.Path
Expand All @@ -21,6 +22,9 @@ class AdminConfigController {
@Inject
private lateinit var configService: ConfigService

@Inject
private lateinit var discordService: DiscordService

@Path
@Get
@AdminSessionAuthenticated
Expand All @@ -46,6 +50,7 @@ class AdminConfigController {
@AdminSessionAuthenticated
private fun postConfig(@PathParam("uuid") uuid: UUID, @BodyParam parameters: Parameters): Response {
configService.update(uuid, parameters)
discordService.init()
return Response.redirect(Link.CONFIG.href)
}
}
14 changes: 9 additions & 5 deletions src/main/kotlin/fr/shikkanime/jobs/FetchEpisodesJob.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package fr.shikkanime.jobs

import fr.shikkanime.converters.AbstractConverter
import fr.shikkanime.dtos.EpisodeDto
import fr.shikkanime.entities.Episode
import fr.shikkanime.services.DiscordService
import fr.shikkanime.services.EpisodeService
import fr.shikkanime.utils.Constant
import fr.shikkanime.utils.LoggerFactory
import fr.shikkanime.utils.isEqualOrAfter
import jakarta.inject.Inject
import java.time.ZoneId
import java.time.ZonedDateTime
Expand All @@ -19,6 +23,9 @@ class FetchEpisodesJob : AbstractJob() {
@Inject
private lateinit var episodeService: EpisodeService

@Inject
private lateinit var discordService: DiscordService

override fun run() {
if (isRunning) {
logger.warning("Job is already running")
Expand Down Expand Up @@ -49,14 +56,11 @@ class FetchEpisodesJob : AbstractJob() {
}

episodes
.filter {
(zonedDateTime.isEqual(it.releaseDateTime) || zonedDateTime.isAfter(it.releaseDateTime)) && !set.contains(
it.hash
)
}
.filter { (zonedDateTime.isEqualOrAfter(it.releaseDateTime)) && !set.contains(it.hash) }
.forEach {
val savedEpisode = episodeService.save(it)
savedEpisode.hash?.let { hash -> set.add(hash) }
discordService.sendEpisodeRelease(AbstractConverter.convert(savedEpisode, EpisodeDto::class.java))
}

isRunning = false
Expand Down
3 changes: 3 additions & 0 deletions src/main/kotlin/fr/shikkanime/modules/DefaultModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import fr.shikkanime.jobs.AbstractJob
import fr.shikkanime.platforms.AbstractPlatform
import fr.shikkanime.repositories.AbstractRepository
import fr.shikkanime.services.AbstractService
import fr.shikkanime.services.DiscordService
import fr.shikkanime.utils.Constant
import fr.shikkanime.utils.Database
import fr.shikkanime.utils.routes.Controller
Expand Down Expand Up @@ -32,5 +33,7 @@ class DefaultModule : AbstractModule() {
Constant.reflections.getTypesAnnotatedWith(Controller::class.java).forEach {
bind(it).asEagerSingleton()
}

bind(DiscordService::class.java).asEagerSingleton()
}
}
5 changes: 1 addition & 4 deletions src/main/kotlin/fr/shikkanime/platforms/AbstractPlatform.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import fr.shikkanime.platforms.configuration.PlatformConfiguration
import fr.shikkanime.utils.Constant
import fr.shikkanime.utils.LoggerFactory
import fr.shikkanime.utils.ObjectParser
import fr.shikkanime.utils.isEqualOrAfter
import kotlinx.coroutines.runBlocking
import java.io.File
import java.lang.reflect.ParameterizedType
Expand Down Expand Up @@ -62,10 +63,6 @@ abstract class AbstractPlatform<C : PlatformConfiguration<*>, K : Any, V> {
file.writeText(ObjectParser.toJson(configuration))
}

private fun ZonedDateTime.isEqualOrAfter(other: ZonedDateTime): Boolean {
return this.isEqual(other) || this.isAfter(other)
}

private fun getConfigurationFile(): File {
val folder = File(Constant.dataFolder, "config")
if (!folder.exists()) folder.mkdirs()
Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/fr/shikkanime/services/ConfigService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class ConfigService : AbstractService<Config, ConfigRepository>() {

fun findByName(name: String) = configRepository.findByName(name)

fun getValueAsString(name: String) = findByName(name)?.propertyValue
fun getValueAsInt(name: String) = findByName(name)?.propertyValue?.toIntOrNull()

fun update(uuid: UUID, parameters: Parameters): Config? {
Expand Down
68 changes: 68 additions & 0 deletions src/main/kotlin/fr/shikkanime/services/DiscordService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package fr.shikkanime.services

import com.google.inject.Inject
import fr.shikkanime.dtos.EpisodeDto
import fr.shikkanime.utils.LoggerFactory
import fr.shikkanime.utils.StringUtils
import net.dv8tion.jda.api.EmbedBuilder
import net.dv8tion.jda.api.JDA
import net.dv8tion.jda.api.JDABuilder
import net.dv8tion.jda.api.entities.Activity
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel
import java.net.URI
import java.time.ZonedDateTime
import java.util.logging.Level
import javax.imageio.ImageIO

class DiscordService {
@Inject
private lateinit var configService: ConfigService

private val logger = LoggerFactory.getLogger(DiscordService::class.java)
private var isInitialized = false
private var jda: JDA? = null

fun init() {
if (isInitialized) return

try {
val builder = JDABuilder.createDefault(configService.getValueAsString("discord_token"))
builder.setActivity(Activity.playing("https://www.shikkanime.fr/"))
jda = builder.build()
jda?.awaitReady()
isInitialized = true
} catch (e: Exception) {
logger.log(Level.SEVERE, "Error while initializing DiscordService", e)
}
}

private fun getTextChannels(): MutableList<TextChannel>? =
jda?.getTextChannelsByName("bot\uD83E\uDD16", true)

fun sendEpisodeRelease(episodeDto: EpisodeDto) {
init()
if (!isInitialized) return
if (episodeDto.image.isBlank()) return

try {
val embedMessage = EmbedBuilder()
val image = ImageIO.read(URI(episodeDto.image).toURL())
embedMessage.setColor(ImageService.getDominantColor(image))
embedMessage.setAuthor(
episodeDto.platform.platformName,
episodeDto.platform.url,
"https://www.shikkanime.fr/admin/assets/img/platforms/${episodeDto.platform.image}"
)
embedMessage.setTitle(episodeDto.anime.shortName, episodeDto.url)
embedMessage.setDescription("**${episodeDto.title ?: "Untitled"}**\n${StringUtils.toEpisodeString(episodeDto)}")
embedMessage.setImage(episodeDto.image)
embedMessage.setFooter("Shikkanime", "https://www.shikkanime.fr/admin/assets/favicons/favicon-64x64.png")
embedMessage.setTimestamp(ZonedDateTime.parse(episodeDto.releaseDateTime).toInstant())
val embed = embedMessage.build()

getTextChannels()?.forEach { it.sendMessageEmbeds(embed).queue() }
} catch (e: Exception) {
logger.log(Level.SEVERE, "Error while sending message to Discord", e)
}
}
}
2 changes: 1 addition & 1 deletion src/main/kotlin/fr/shikkanime/services/ImageService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ object ImageService {

operator fun get(uuid: UUID): Image? = cache.find { it.uuid == uuid.toString() }

private fun getDominantColor(image: BufferedImage): Color {
fun getDominantColor(image: BufferedImage): Color {
val pixels = IntArray(image.width * image.height).apply {
image.getRGB(
0,
Expand Down
7 changes: 7 additions & 0 deletions src/main/kotlin/fr/shikkanime/utils/Extensions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package fr.shikkanime.utils

import java.time.ZonedDateTime

fun ZonedDateTime.isEqualOrAfter(other: ZonedDateTime): Boolean {
return this.isEqual(other) || this.isAfter(other)
}
24 changes: 24 additions & 0 deletions src/main/resources/db/changelog/2024/01/03-changelog.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.25.xsd"
objectQuotingStrategy="QUOTE_ONLY_RESERVED_WORDS">
<property global="false" name="id" value="1704810005026"/>
<property global="false" name="author" value="Ziedelth"/>

<changeSet id="${id}-1" author="${author}" dbms="postgresql">
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="0">SELECT COUNT(*)
FROM config
WHERE property_key = 'discord_token'</sqlCheck>
</preConditions>

<insert tableName="config">
<column name="uuid" valueComputed="gen_random_uuid()"/>
<column name="property_key" value="discord_token"/>
<column name="property_value" value=""/>
</insert>
</changeSet>
</databaseChangeLog>
1 change: 1 addition & 0 deletions src/main/resources/db/changelog/db.changelog-master.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
<include file="/db/changelog/2023/12/02-changelog.xml"/>
<include file="/db/changelog/2024/01/01-changelog.xml"/>
<include file="/db/changelog/2024/01/02-changelog.xml"/>
<include file="/db/changelog/2024/01/03-changelog.xml"/>
</databaseChangeLog>

0 comments on commit c4644d8

Please sign in to comment.