Skip to content

Commit

Permalink
Finished adding basic database support for storing default language
Browse files Browse the repository at this point in the history
  • Loading branch information
DoggySazHi committed Jan 25, 2024
1 parent 0f26565 commit 18cb018
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 28 deletions.
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,20 @@ Future versions of this plugin will allow for the use of other translation servi
## Configuration (as of 1.1.0)

```yaml

deepl-api-url: # The API link for DeepL: free edition is https://api-free.deepl.com/v2/translate, but Pro users can use https://api.deepl.com/v2/translate
deepl-api-key: # Your API key for DeepL - most likely ends with ":fx" for free users
default-language: # The default language to translate to, e.g. en-US
ratelimit:
token_bucket_capacity: # The max number of characters that can be translated at one time
token_refill_rate: # The number of characters that can be translated per second
storage:
type: # Either "sqlite" or "mysql"
sqlite:
file: # Path to your SQLite database file, e.g. kosuzu.db. The plugin will create the tables automatically
mysql:
host: # Hostname of your MySQL server, e.g. localhost
port: # Port of your MySQL server, e.g. 3306
database: # Name of your MySQL database, e.g. kosuzu; the plugin will create the tables automatically
username: # Username to your MySQL database
password: # Password to your MySQL database
```
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ repositories {

dependencies {
compileOnly "io.papermc.paper:paper-api:1.20.2-R0.1-SNAPSHOT"
compileOnly "com.comphenix.protocol:ProtocolLib:5.2.0-SNAPSHOT"
// compileOnly "com.comphenix.protocol:ProtocolLib:5.2.0-SNAPSHOT"
implementation 'com.github.mizosoft.methanol:methanol:1.7.0'
implementation 'com.github.mizosoft.methanol:methanol-brotli:1.7.0'
implementation "org.xerial:sqlite-jdbc:3.45.0.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package net.gensokyoreimagined.motoori;

import org.apache.commons.dbcp2.BasicDataSource;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;

Expand All @@ -16,12 +15,18 @@
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import java.util.logging.Logger;

public class KosuzuRemembersEverything {
private final YamlConfiguration translations;
private final BasicDataSource dataSource = new BasicDataSource();
private final Logger logger;

private boolean isSqlite = false;

public KosuzuRemembersEverything() {
logger = Kosuzu.getInstance().getLogger();

var translationFile = Kosuzu.getInstance().getResource("translations.yml");
if (translationFile == null) {
throw new RuntimeException("Failed to find translations.yml! Is the plugin jar corrupted?");
Expand All @@ -40,6 +45,7 @@ public KosuzuRemembersEverything() {

switch (type) {
case "sqlite":
isSqlite = true;
initializeSqlite();
break;
case "mysql":
Expand Down Expand Up @@ -74,17 +80,17 @@ private void initializeSqlite() {
if (!Files.exists(pathObj))
Files.createFile(pathObj);
} catch (IOException e) {
Bukkit.getLogger().severe("Failed to create SQLite database file! Maybe check your permissions? Writing to: " + path);
logger.severe("Failed to create SQLite database file! Maybe check your permissions? Writing to: " + path);
throw new RuntimeException(e);
}

try {
dataSource.setUrl("jdbc:sqlite:" + path);
dataSource.setUrl("jdbc:sqlite:plugins/Kosuzu/" + path);
dataSource.setMinIdle(5);
dataSource.setMaxIdle(10);
dataSource.setMaxOpenPreparedStatements(50);
} catch (Exception e) {
Bukkit.getLogger().severe("Failed to connect to SQLite database! Writing to: " + path);
logger.severe("Failed to connect to SQLite database! Writing to: " + path);
throw new RuntimeException(e);
}
}
Expand All @@ -109,7 +115,7 @@ private void initializeMySQL() {
dataSource.setMaxIdle(20);
dataSource.setMaxOpenPreparedStatements(100);
} catch (Exception e) {
Bukkit.getLogger().severe("Failed to connect to MySQL database! Connecting to: " + host + ":" + port + "/" + database);
logger.severe("Failed to connect to MySQL database! Connecting to: " + host + ":" + port + "/" + database);
throw new RuntimeException(e);
}
}
Expand Down Expand Up @@ -138,19 +144,29 @@ private void initializeDatabase() {
}

for (var language : KosuzuHintsEverything.LANGUAGES) {
try (var insert = connection.prepareStatement("INSERT IGNORE INTO `language` (`code`, `native_name`, `english_name`) VALUES (?, ?, ?)")) {
try (var insert = connection.prepareStatement(s("INSERT IGNORE INTO `language` (`code`, `native_name`, `english_name`) VALUES (?, ?, ?)"))) {
insert.setString(1, language);
insert.setString(2, getTranslation("language.native", language));
insert.setString(3, getTranslation("language.english", language));
insert.execute();
}
}
} catch (SQLException e) {
Bukkit.getLogger().severe("Failed to initialize database!");
logger.severe("Failed to initialize database!");
throw new RuntimeException(e);
}
}

private String s(String sql) {
if (!isSqlite) {
return sql;
}

return sql
.replace("AUTO_INCREMENT", "AUTOINCREMENT")
.replace("INSERT IGNORE", "INSERT OR IGNORE");
}

@NotNull
public String getUserDefaultLanguage(UUID uuid) {
try (var connection = getConnection()) {
Expand All @@ -162,8 +178,8 @@ public String getUserDefaultLanguage(UUID uuid) {
}
}
} catch (SQLException e) {
Bukkit.getLogger().severe("Failed to get user default language!");
Bukkit.getLogger().severe(e.getMessage());
logger.severe("Failed to get user default language!");
logger.severe(e.getMessage());
}

return Kosuzu.getInstance().config.getString("default-language", "EN-US");
Expand All @@ -172,7 +188,7 @@ public String getUserDefaultLanguage(UUID uuid) {
@NotNull
public Collection<String> getUserLanguages(String uuid) {
try (var connection = getConnection()) {
try (var statement = connection.prepareStatement("SELECT `language` FROM `language` WHERE `uuid` = ?")) {
try (var statement = connection.prepareStatement("SELECT `language` FROM `multilingual` WHERE `uuid` = ?")) {
statement.setString(1, uuid);
var result = statement.executeQuery();
// collect results into a collection
Expand All @@ -185,24 +201,30 @@ public Collection<String> getUserLanguages(String uuid) {
return output;
}
} catch (SQLException e) {
Bukkit.getLogger().severe("Failed to get user languages!");
Bukkit.getLogger().severe(e.getMessage());
logger.severe("Failed to get user languages!");
logger.severe(e.getMessage());
}

return List.of(Kosuzu.getInstance().config.getString("default-language", "EN-US"));
}

public void setUserDefaultLanguage(UUID uuid, String lang) {
try (var connection = getConnection()) {
try (var statement = connection.prepareStatement("INSERT INTO `user` (`uuid`, `default_language`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `default_language` = ?")) {
// i want to do ON DUPLICATE KEY UPDATE, but ugh compatibility
try (var statement = connection.prepareStatement(s("INSERT IGNORE INTO `user` (`uuid`, `default_language`) VALUES (?, ?); UPDATE `user` SET `default_language` = ? WHERE `uuid` = ?;"))) {
statement.setString(1, uuid.toString());
statement.setString(2, lang);
statement.setString(3, lang);
statement.execute();
}

try (var statement = connection.prepareStatement(s("UPDATE `user` SET `default_language` = ? WHERE `uuid` = ?;"))) {
statement.setString(1, lang);
statement.setString(2, uuid.toString());
statement.execute();
}
} catch (SQLException e) {
Bukkit.getLogger().severe("Failed to set user default language!");
Bukkit.getLogger().severe(e.getMessage());
logger.severe("Failed to set user default language!");
logger.severe(e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,15 @@ private DeepLTranslation translateViaMobileRPC(String input, @Nullable String la
var body = response.body();

if (statusCode != 200) {
Bukkit.getLogger().warning("[Kosuzu] Failed to send request to DeepL via mobile API:\n" + body);
Kosuzu.getInstance().getLogger().warning("Failed to send request to DeepL via mobile API:\n" + body);
return null;
}

var deeplResponse = gson.fromJson(body, DeepLMobileResponse.class);
return deeplResponse.getTranslation();
}
catch (Exception e) {
Bukkit.getLogger().warning("[Kosuzu] Failed to send request to DeepL via mobile API:\n" + e.getMessage());
Kosuzu.getInstance().getLogger().warning("Failed to send request to DeepL via mobile API:\n" + e.getMessage());
return null;
}
}
Expand All @@ -88,7 +88,7 @@ private DeepLTranslation translateViaAPI(String input, @Nullable String language
var config = Kosuzu.getInstance().config;
var key = config.getString("deepl-api-key");
if (key == null || key.equals("changeme")) {
Bukkit.getLogger().warning("[Kosuzu] Please set your DeepL API key in config.yml");
Kosuzu.getInstance().getLogger().warning("Please set your DeepL API key in config.yml");
return null;
}

Expand All @@ -113,23 +113,23 @@ private DeepLTranslation translateViaAPI(String input, @Nullable String language
var body = response.body();

if (statusCode != 200) {
Bukkit.getLogger().warning("[Kosuzu] Failed to send request to DeepL:\n" + body);
Kosuzu.getInstance().getLogger().warning("Failed to send request to DeepL:\n" + body);
return null;
}

var deeplResponse = gson.fromJson(body, DeepLResponse.class);
return deeplResponse.getTranslation();
}
catch (Exception e) {
Bukkit.getLogger().warning("[Kosuzu] Failed to send request to DeepL:\n" + e.getMessage());
Kosuzu.getInstance().getLogger().warning("Failed to send request to DeepL:\n" + e.getMessage());
return null;
}
}

public DeepLTranslation translate(String input, @Nullable String language) {
var translation = translateViaMobileRPC(input, language);
if (translation == null) {
Bukkit.getLogger().warning("[Kosuzu] Falling back to DeepL API");
Kosuzu.getInstance().getLogger().warning("Falling back to DeepL API");
translation = translateViaAPI(input, language);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ private void translateCallback(AsyncChatEvent event, Audience player) {
var translation = translator.translate(message, language);

if (translation == null) {
event.getPlayer().sendMessage(
player.sendMessage(
Component.text()
.content(Kosuzu.getInstance().database.getTranslation("translate.fail", language))
.color(NamedTextColor.RED)
Expand All @@ -63,7 +63,7 @@ private void translateCallback(AsyncChatEvent event, Audience player) {
return;
}

event.getPlayer().sendMessage(
player.sendMessage(
Component
.text()
.append(
Expand Down
3 changes: 1 addition & 2 deletions src/main/resources/plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ name: Kosuzu
version: '${version}'
main: net.gensokyoreimagined.motoori.Kosuzu
api-version: '1.20'
depend:
softdepend:
- ProtocolLib
commands:
kosuzu:
usage: /kosuzu <subcommand> <options>
description: Control the translation system
permission: kosuzu.translate

0 comments on commit 18cb018

Please sign in to comment.