Skip to content

Commit

Permalink
Merge pull request #101 from Blad3Mak3r/feature/i18n
Browse files Browse the repository at this point in the history
v0.13 - Add support for Spanish servers
  • Loading branch information
Blad3Mak3r committed Jul 4, 2021
2 parents 9fccd54 + 9a7f238 commit e7e832a
Show file tree
Hide file tree
Showing 96 changed files with 1,952 additions and 664 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ val prometheusVersion = "0.11.0"
val sentryVersion = "5.0.1"

group = "dev.killjoy"
val versionObj = Version(0, 12, 6)
val versionObj = Version(0, 13)
version = versionObj.build()

repositories {
Expand Down
3 changes: 2 additions & 1 deletion src/main/kotlin/dev/killjoy/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ const val REPOSITORY_URL = "https://github.com/Blad3Mak3r/Killjoy"
const val WEBSITE_URL = "https://killjoy.dev"
const val BUG_REPORT_URL = "https://github.com/Blad3Mak3r/Killjoy/issues/new?template=bug_report.md"
const val VOTE_URL = "https://top.gg/bot/706887214088323092/vote"
const val SPONSOR_URL = "https://github.com/sponsors/Blad3Mak3r"
const val SPONSOR_URL = "https://github.com/sponsors/Blad3Mak3r"
const val GUIDES_URL = "https://www.reddit.com/r/KilljoyBot/collection/60fca796-806c-4876-9f37-25e1c0de3a56"
15 changes: 0 additions & 15 deletions src/main/kotlin/dev/killjoy/Credentials.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,6 @@
* See the License for the specific language governing permissions and limitations under the License.
******************************************************************************/

/*******************************************************************************
* Copyright (c) 2021. Blademaker
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
******************************************************************************/

package dev.killjoy

import com.typesafe.config.Config
Expand Down
8 changes: 4 additions & 4 deletions src/main/kotlin/dev/killjoy/Killjoy.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
package dev.killjoy

import dev.killjoy.database.DatabaseConnection
import dev.killjoy.valorant.AgentAbility
import dev.killjoy.valorant.ValorantAgent
import dev.killjoy.valorant.ValorantMap
import dev.killjoy.valorant.ValorantWeapon
import dev.killjoy.valorant.agent.AgentAbility
import dev.killjoy.valorant.agent.ValorantAgent
import dev.killjoy.valorant.map.ValorantMap
import dev.killjoy.valorant.arsenal.ValorantWeapon
import net.dv8tion.jda.api.sharding.ShardManager

interface Killjoy {
Expand Down
24 changes: 15 additions & 9 deletions src/main/kotlin/dev/killjoy/Launcher.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import dev.killjoy.apis.stats.Website
import dev.killjoy.database.Database
import dev.killjoy.database.DatabaseConnection
import dev.killjoy.database.buildDatabaseConnection
import dev.killjoy.extensions.jda.supportedLocale
import dev.killjoy.framework.CommandRegistry
import dev.killjoy.i18n.I18n
import dev.killjoy.listeners.MainListener
import dev.killjoy.prometheus.Prometheus
import dev.killjoy.slash.api.handler.DefaultSlashCommandHandler
Expand All @@ -31,13 +33,14 @@ import dev.killjoy.utils.Loaders
import dev.killjoy.utils.SentryUtils
import dev.killjoy.utils.Utils
import dev.killjoy.utils.extensions.isInt
import dev.killjoy.valorant.AgentAbility
import dev.killjoy.valorant.ValorantAgent
import dev.killjoy.valorant.ValorantMap
import dev.killjoy.valorant.ValorantWeapon
import dev.killjoy.valorant.agent.AgentAbility
import dev.killjoy.valorant.agent.ValorantAgent
import dev.killjoy.valorant.map.ValorantMap
import dev.killjoy.valorant.arsenal.ValorantWeapon
import dev.killjoy.webhook.WebhookUtils
import net.dv8tion.jda.api.entities.Activity
import net.dv8tion.jda.api.entities.ApplicationInfo
import net.dv8tion.jda.api.entities.Guild
import net.dv8tion.jda.api.requests.GatewayIntent
import net.dv8tion.jda.api.sharding.DefaultShardManagerBuilder
import net.dv8tion.jda.api.sharding.ShardManager
Expand Down Expand Up @@ -99,6 +102,8 @@ object Launcher : Killjoy {

database = buildDatabaseConnection()

I18n.init()

// Load entities after banner
agents = Loaders.loadAgents()
arsenal = Loaders.loadArsenal()
Expand Down Expand Up @@ -160,11 +165,11 @@ object Launcher : Killjoy {
}

override fun getWeapon(name: String): ValorantWeapon? {
return arsenal.find { it.name.equals(name, true) }
return arsenal.find { it.names.any { w -> w.equals(name, true) } }
}

override fun getWeaponById(id: String): ValorantWeapon? {
return arsenal.find { it.id.equals(id, true) }
return arsenal.find { it.ids.any { _id -> _id.equals(id,true) } }
}

override fun getMap(name: String): ValorantMap? {
Expand All @@ -180,11 +185,12 @@ object Launcher : Killjoy {
}

override fun getAbility(name: String): AgentAbility? {
return getAbilities().find { it.skill.name.equals(name, true) }
val n = name.lowercase()
return getAbilities().find {
it.name.containsValue(n) || it.name.containsValue(n.replace("_", " "))
}
}

fun getSkills() = agents.map { it.skills }.reduce { acc, list -> acc + list }

private fun enableListing() {
try {
val websites = Credentials.getNullableConfigList("listing")?.map { Website(it) }
Expand Down
15 changes: 0 additions & 15 deletions src/main/kotlin/dev/killjoy/apis/memes/Meme.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,6 @@
* See the License for the specific language governing permissions and limitations under the License.
******************************************************************************/

/*******************************************************************************
* Copyright (c) 2021. Blademaker
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
******************************************************************************/

package dev.killjoy.apis.memes

import org.json.JSONObject
Expand Down
15 changes: 0 additions & 15 deletions src/main/kotlin/dev/killjoy/apis/memes/Memes4K.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,6 @@
* See the License for the specific language governing permissions and limitations under the License.
******************************************************************************/

/*******************************************************************************
* Copyright (c) 2021. Blademaker
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
******************************************************************************/

package dev.killjoy.apis.memes

import io.ktor.client.*
Expand Down
21 changes: 21 additions & 0 deletions src/main/kotlin/dev/killjoy/apis/news/I18nCachedNews.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*******************************************************************************
* Copyright (c) 2021. Blademaker
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
******************************************************************************/

package dev.killjoy.apis.news

data class I18nCachedNews(
val news: List<ValorantNew>,
val timestamp: Long
)
47 changes: 33 additions & 14 deletions src/main/kotlin/dev/killjoy/apis/news/NewsRetriever.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,43 @@

package dev.killjoy.apis.news

import dev.killjoy.i18n.I18n
import kong.unirest.Unirest
import kong.unirest.json.JSONObject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.future.await
import kotlinx.coroutines.withContext
import org.slf4j.LoggerFactory
import java.util.*
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicReference
import kotlin.collections.HashMap

object NewsRetriever {
private var cachedNews: AtomicReference<List<ValorantNew>?> = AtomicReference(null)
private var cachedNewsTimestamp: Long = 0L
private val cacheV2 = ConcurrentHashMap<String, I18nCachedNews>()
private val logger = LoggerFactory.getLogger(NewsRetriever::class.java)

val cached: Boolean
get() = cachedNews.get() != null && cachedNewsTimestamp > System.currentTimeMillis()
fun isCached(locale: Locale): Boolean {
val cached = cacheV2[locale.language] ?: return false

suspend fun lastNews(): List<ValorantNew> = withContext(Dispatchers.IO) {
if (!cached) {
retrieveExperimentalValorantNews().await()
return cached.timestamp > System.currentTimeMillis()
}

suspend fun lastNews(locale: Locale): List<ValorantNew> = withContext(Dispatchers.IO) {
if (!isCached(locale)) {
retrieveExperimentalValorantNews(locale).await()
} else {
cachedNews.get()!!
cacheV2[locale.language]!!.news
}
}

private fun retrieveExperimentalValorantNews(): CompletableFuture<List<ValorantNew>> = CompletableFuture.supplyAsync {
logger.info("Retrieving fresh Valorant news from data api...")
private fun retrieveExperimentalValorantNews(locale: Locale): CompletableFuture<List<ValorantNew>> = CompletableFuture.supplyAsync {
logger.info("Retrieving fresh Valorant news from data api for locale ${locale.language} ...")

val response = Unirest.get("https://playvalorant.com/page-data/en-us/news/page-data.json").asJson()
val localePath = getLocalePath(locale)
val response = Unirest.get("https://playvalorant.com/page-data/$localePath/news/page-data.json").asJson()

if (!response.isSuccess) throw IllegalStateException("Non-successful status code: ${response.status}")

Expand All @@ -56,14 +63,26 @@ object NewsRetriever {
.toList()
.map { it as JSONObject }

val mappedResults = contentArray.take(5).mapNotNull(ValorantNew::buildFromExperimentalApi)
val mappedResults = contentArray.take(5).mapNotNull { ValorantNew.buildFromExperimentalApi(localePath, it) }

if (mappedResults.isNotEmpty()) {
cachedNews.set(mappedResults)
cachedNewsTimestamp = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1)
val newsObj = I18nCachedNews(
news = mappedResults,
timestamp = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1)
)
cacheV2[locale.language] = newsObj
}

logger.info("Successfully retrieved valorant news.")
mappedResults
}

fun getLocalePath(locale: Locale): String {
val usedLocale = if (I18n.isSupported(locale)) locale else I18n.DEFAULT_LOCALE

return when (usedLocale.language) {
"es" -> "es-es"
else -> "en-us"
}
}
}
13 changes: 8 additions & 5 deletions src/main/kotlin/dev/killjoy/apis/news/ValorantNew.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@

package dev.killjoy.apis.news

import dev.killjoy.i18n.i18nCommand
import dev.killjoy.utils.ParseUtils
import kong.unirest.json.JSONObject
import net.dv8tion.jda.api.entities.Guild
import net.dv8tion.jda.api.entities.MessageEmbed
import org.slf4j.LoggerFactory
import java.text.MessageFormat
import java.text.SimpleDateFormat
import java.time.LocalDate
import java.time.format.DateTimeFormatter
Expand All @@ -32,16 +35,16 @@ data class ValorantNew(
val image: String
) {

fun asEmbedField(): MessageEmbed.Field {
fun asEmbedField(guild: Guild): MessageEmbed.Field {
return MessageEmbed.Field(
title,
fieldPattern.format(description, url, date),
MessageFormat.format(getFieldPattern(guild), description, url, date),
false
)
}

companion object {
private const val fieldPattern = "%s\n[` Read more... `](%s) | ` Posted on %s `"
private fun getFieldPattern(guild: Guild) = guild.i18nCommand("news.fieldPattern")
private val inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH)
private val outputFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy", Locale.ENGLISH)
private val logger = LoggerFactory.getLogger(ValorantNew::class.java)
Expand All @@ -51,7 +54,7 @@ data class ValorantNew(
return outputFormatter.format(formatted)
}

fun buildFromExperimentalApi(json: JSONObject): ValorantNew? {
fun buildFromExperimentalApi(localePath: String, json: JSONObject): ValorantNew? {
try {
val title = json.getString("title")
val description = json.getString("description")
Expand All @@ -63,7 +66,7 @@ data class ValorantNew(

return ValorantNew(
title = title,
url = externalLink ?: "https://playvalorant.com/en-us$url",
url = externalLink ?: "https://playvalorant.com/$localePath$url",
date = formatDate(json.getString("date")),
description = description,
image = banner
Expand Down
15 changes: 0 additions & 15 deletions src/main/kotlin/dev/killjoy/apis/riot/entities/AgentStats.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,6 @@
* See the License for the specific language governing permissions and limitations under the License.
******************************************************************************/

/*******************************************************************************
* Copyright (c) 2021. Blademaker
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and limitations under the License.
******************************************************************************/

package dev.killjoy.apis.riot.entities

import org.json.JSONObject
Expand Down
19 changes: 13 additions & 6 deletions src/main/kotlin/dev/killjoy/commands/game/AbilitiesSlashCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
package dev.killjoy.commands.game

import dev.killjoy.Launcher
import dev.killjoy.i18n.I18nKey
import dev.killjoy.i18n.i18n
import dev.killjoy.i18n.i18nCommand
import dev.killjoy.slash.api.AbstractSlashCommand
import dev.killjoy.slash.api.SlashCommandContext
import dev.killjoy.slash.api.annotations.SlashSubCommand
Expand All @@ -26,7 +29,8 @@ class AbilitiesSlashCommand : AbstractSlashCommand("abilities") {

@SlashSubCommand("all")
override suspend fun handle(ctx: SlashCommandContext) {
val abilities = Launcher.getAbilities().sortedBy { it.skill.name }

val abilities = Launcher.getAbilities().sortedBy { it.name(ctx.guild) }

val page = ctx.getOption("page")?.asString?.toInt() ?: 1

Expand All @@ -37,18 +41,21 @@ class AbilitiesSlashCommand : AbstractSlashCommand("abilities") {
val lastIndex = (firstIndex + MAX_ABILITIES_PER_PAGE).coerceAtMost(abilities.size)

ctx.replyEmbed {
setTitle("Valorant Abilities")
setTitle(ctx.i18n(I18nKey.VALORANT_ABILITIES_TITLE))
setDescription("")
for (index in firstIndex until lastIndex) {
val ability = abilities[index]

val body = buildString {
appendLine(ability.skill.info)
appendLine("**Cost**: ${ability.skill.cost}")
appendLine(ability.description(ctx.guild))
appendLine("**${ctx.i18n(I18nKey.ABILITY_COST)}**: ${ability.cost}")
}
addField("${ability.skill.name} (${ability.agent.name})", body, false)
addField("${ability.name(ctx.guild)} (${ability.agent.name})", body, false)
}
setFooter("Page ${pageIndex + 1} / $totalPages | Showing ${firstIndex + 1} - $lastIndex of ${abilities.size} abilities.")
val f0 = pageIndex + 1
val f2 = firstIndex + 1
val f4 = abilities.size
setFooter(ctx.i18nCommand("abilities.footer", f0, totalPages, f2, lastIndex, f4))
}.queue()
}

Expand Down
Loading

0 comments on commit e7e832a

Please sign in to comment.