package tools.messages.translation; import com.google.common.io.Resources; import com.google.gson.Gson; import fr.xephi.authme.message.MessageKey; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import tools.messages.MessageFileVerifier; import tools.messages.VerifyMessagesTask; import tools.utils.FileUtils; import tools.utils.ToolTask; import tools.utils.ToolsConstants; import java.io.File; import java.io.IOException; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.HashSet; import java.util.Scanner; import java.util.Set; import java.util.regex.Pattern; /** * Imports a message file from a remote JSON export and validates the resulting file. *

* Comments at the top of an existing file should remain after the import, but it is important * to verify that no unwanted changes have been applied to the file. Note that YAML comments * tend to disappear if there is no space between the # and the first character. */ public class ImportMessagesTask implements ToolTask { private static final String MESSAGES_FOLDER = ToolsConstants.MAIN_RESOURCES_ROOT + "messages/"; private Gson gson = new Gson(); private Set messageCodes; @Override public String getTaskName() { return "importMessages"; } @Override public void execute(Scanner scanner) { System.out.println("Enter URL to import from"); // Dirty trick: replace https:// with http:// so we don't have to worry about installing certificates... String url = scanner.nextLine().replace("https://", "http://"); LanguageExport languageExport = getLanguageExportFromUrl(url); if (languageExport == null) { throw new IllegalStateException("An error occurred: constructed language export is null"); } mergeExportIntoFile(languageExport); System.out.println("Saved to messages file for code '" + languageExport.code + "'"); } private LanguageExport getLanguageExportFromUrl(String location) { try { URL url = new URL(location); String json = Resources.toString(url, StandardCharsets.UTF_8); return gson.fromJson(json, LanguageExport.class); } catch (IOException e) { throw new IllegalStateException(e); } } private void mergeExportIntoFile(LanguageExport export) { String languageCode = export.code; String fileName = MESSAGES_FOLDER + "messages_" + languageCode + ".yml"; File file = new File(fileName); FileConfiguration fileConfiguration; if (file.exists()) { removeAllTodoComments(fileName); fileConfiguration = AuthMeYamlConfiguration.loadConfiguration(file); } else { fileConfiguration = new AuthMeYamlConfiguration(); } buildMessageCodeList(); for (MessageExport messageExport : export.messages) { if (!messageCodes.contains(messageExport.key)) { throw new IllegalStateException("Message key '" + messageExport.key + "' does not exist"); } else if (!messageExport.translatedMessage.isEmpty()) { fileConfiguration.set(messageExport.key, messageExport.translatedMessage); } } try { fileConfiguration.save(file); } catch (IOException e) { throw new IllegalStateException(e); } MessageFileVerifier verifier = new MessageFileVerifier(file); VerifyMessagesTask.verifyFileAndAddKeys(verifier, YamlConfiguration.loadConfiguration( new File(MESSAGES_FOLDER + "messages_en.yml"))); } private void buildMessageCodeList() { messageCodes = new HashSet<>(MessageKey.values().length); for (MessageKey messageKey : MessageKey.values()) { messageCodes.add(messageKey.getKey()); } } /** * Removes all to-do comments written by {@link VerifyMessagesTask}. This is helpful as the YamlConfiguration * moves those comments otherwise upon saving. * * @param file The file whose to-do comments should be removed */ private static void removeAllTodoComments(String file) { String contents = FileUtils.readFromFile(file); String regex = "^# TODO .*$"; contents = Pattern.compile(regex, Pattern.MULTILINE).matcher(contents).replaceAll(""); FileUtils.writeToFile(file, contents); } }