New Placeholder system and Localization system

This commit is contained in:
Ilya 2020-12-20 18:30:59 +03:00
parent 41bb8be727
commit 24304e4bbc
23 changed files with 173 additions and 79 deletions

View File

@ -1,11 +1,11 @@
package ru.redguy.webinfomod; package ru.redguy.webinfomod;
import fi.iki.elonen.NanoHTTPD; import fi.iki.elonen.NanoHTTPD;
import ru.redguy.webinfomod.langs.LangFile; import ru.redguy.webinfomod.langs.Localization;
import java.io.IOException; import java.io.IOException;
public interface IWebPage { public interface IWebPage {
public NanoHTTPD.Response getPage(Config config, LangFile langFile, NanoHTTPD.IHTTPSession session) throws IOException; public NanoHTTPD.Response getPage(Config config, NanoHTTPD.IHTTPSession session) throws IOException;
} }

View File

@ -5,7 +5,9 @@ import org.slf4j.Logger;
import org.spongepowered.api.event.game.state.GameStartedServerEvent; import org.spongepowered.api.event.game.state.GameStartedServerEvent;
import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.Listener;
import org.spongepowered.api.plugin.Plugin; import org.spongepowered.api.plugin.Plugin;
import ru.redguy.webinfomod.langs.LangFile; import ru.redguy.webinfomod.langs.Localization;
import ru.redguy.webinfomod.utils.BasePlaceholders;
import ru.redguy.webinfomod.utils.PlaceholdersUtils;
import java.io.IOException; import java.io.IOException;
@ -26,13 +28,13 @@ public class WebInfoSponge {
public ru.redguy.webinfomod.Logger myLogger; public ru.redguy.webinfomod.Logger myLogger;
public Config config; public Config config;
public WebServer webServer; public WebServer webServer;
public LangFile langFile;
@Listener @Listener
public void onServerStart(GameStartedServerEvent event) throws IOException { public void onServerStart(GameStartedServerEvent event) throws IOException {
myLogger = new ru.redguy.webinfomod.Logger(logger); myLogger = new ru.redguy.webinfomod.Logger(logger);
config = new Config(myLogger); config = new Config(myLogger);
langFile = new LangFile(config); Localization.loadLangFile(config);
webServer = new WebServer(config.getInt("WebPort"), config, langFile); BasePlaceholders.registerBase();
webServer = new WebServer(config.getInt("WebPort"), config);
} }
} }

View File

@ -10,7 +10,7 @@ import org.reflections.scanners.TypeAnnotationsScanner;
import org.reflections.util.ClasspathHelper; import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder; import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder; import org.reflections.util.FilterBuilder;
import ru.redguy.webinfomod.langs.LangFile; import ru.redguy.webinfomod.langs.Localization;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -20,9 +20,8 @@ public class WebServer extends NanoHTTPD {
Config config; Config config;
Reflections reflections; Reflections reflections;
LangFile langFile;
public WebServer(int port, Config config, LangFile langFile) throws IOException { public WebServer(int port, Config config) throws IOException {
super(port); super(port);
ConfigurationBuilder configBuilder = ConfigurationBuilder configBuilder =
new ConfigurationBuilder() new ConfigurationBuilder()
@ -37,7 +36,6 @@ public class WebServer extends NanoHTTPD {
this.reflections = new Reflections(configBuilder); this.reflections = new Reflections(configBuilder);
start(NanoHTTPD.SOCKET_READ_TIMEOUT, false); start(NanoHTTPD.SOCKET_READ_TIMEOUT, false);
this.config = config; this.config = config;
this.langFile = langFile;
} }
@Override @Override
@ -55,7 +53,7 @@ public class WebServer extends NanoHTTPD {
for (Class<?> mClass : reflections.getTypesAnnotatedWith(WebPage.class, true)) { for (Class<?> mClass : reflections.getTypesAnnotatedWith(WebPage.class, true)) {
if (mClass.getAnnotation(WebPage.class).url().equals(session.getUri())) { if (mClass.getAnnotation(WebPage.class).url().equals(session.getUri())) {
try { try {
return (Response) mClass.getMethod("getPage", Config.class, LangFile.class, IHTTPSession.class).invoke(mClass.newInstance(), config, langFile, session); return (Response) mClass.getMethod("getPage", Config.class, IHTTPSession.class).invoke(mClass.newInstance(), config, session);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
e.printStackTrace(); e.printStackTrace();
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {

View File

@ -9,23 +9,21 @@ import org.apache.commons.io.IOUtils;
import java.io.*; import java.io.*;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
public class LangFile { public class Localization {
private JsonObject jsonObject;
public LangFile(Config config) throws IOException { private static JsonObject jsonObject;
public static void loadLangFile(Config config) throws IOException {
JsonParser parser = new JsonParser(); JsonParser parser = new JsonParser();
Object obj = parser.parse( Object obj = parser.parse(
IOUtils.toString( IOUtils.toString(
LangFile.class.getResourceAsStream( Localization.class.getResourceAsStream(
"/resources/langs/"+config.getString("lang")+".json" "/resources/langs/"+config.getString("lang")+".json"
), StandardCharsets.UTF_8)); ), StandardCharsets.UTF_8));
jsonObject = (JsonObject) obj; jsonObject = (JsonObject) obj;
} }
public LangFile(JsonObject jsonObject) { public static RootCategory getCategory(RootCategories category) {
this.jsonObject = jsonObject;
}
public RootCategory getCategory(RootCategories category) {
switch (category) { switch (category) {
case Links: case Links:
return new Links(jsonObject.getAsJsonObject("Links")); return new Links(jsonObject.getAsJsonObject("Links"));

View File

@ -12,7 +12,11 @@ public class Titles implements RootCategory {
@Override @Override
public String getString(Object object) { public String getString(Object object) {
return jsonObject.get(((ru.redguy.webinfomod.langs.enums.Titles)object).getName()).getAsString(); if(object instanceof String) {
return jsonObject.get((String) object).getAsString();
} else {
return jsonObject.get(((ru.redguy.webinfomod.langs.enums.Titles) object).getName()).getAsString();
}
} }
@Override @Override

View File

@ -13,7 +13,11 @@ public class Words implements RootCategory {
@Override @Override
public String getString(Object object) { public String getString(Object object) {
return jsonObject.get(((ru.redguy.webinfomod.langs.enums.Words)object).getName()).getAsString(); if(object instanceof String) {
return jsonObject.get((String) object).getAsString();
} else {
return jsonObject.get(((ru.redguy.webinfomod.langs.enums.Titles) object).getName()).getAsString();
}
} }
@Override @Override

View File

@ -3,27 +3,20 @@ package ru.redguy.webinfomod.pages;
import fi.iki.elonen.NanoHTTPD; import fi.iki.elonen.NanoHTTPD;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import ru.redguy.webinfomod.*; import ru.redguy.webinfomod.*;
import ru.redguy.webinfomod.langs.LangFile; import ru.redguy.webinfomod.langs.Localization;
import ru.redguy.webinfomod.langs.enums.Links; import ru.redguy.webinfomod.langs.enums.Links;
import ru.redguy.webinfomod.langs.enums.RootCategories; import ru.redguy.webinfomod.langs.enums.RootCategories;
import ru.redguy.webinfomod.utils.PlaceholdersUtils;
import ru.redguy.webinfomod.utils.WebUtils; import ru.redguy.webinfomod.utils.WebUtils;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@WebPage(url = "/") @WebPage(url = "/")
public class Index implements IWebPage { public class Index implements IWebPage {
public NanoHTTPD.Response getPage(Config config, LangFile langFile, NanoHTTPD.IHTTPSession session) throws IOException { public NanoHTTPD.Response getPage(Config config, NanoHTTPD.IHTTPSession session) throws IOException {
String path = "/resources/web/pages/Index.html"; String path = "/resources/web/index.html";
String page = IOUtils.toString(WebServer.class.getResourceAsStream(path), StandardCharsets.UTF_8); String page = IOUtils.toString(WebServer.class.getResourceAsStream(path), StandardCharsets.UTF_8);
WebUtils.CookieHandler ch = new WebUtils.CookieHandler(session.getHeaders()); return NanoHTTPD.newFixedLengthResponse(new PlaceholdersUtils(session).work(page));
if(ch.read("session") == null) {
page = page.replace("<replace id=\"1\"/>","<a href=\"auth/\" class=\"authLink\">"+langFile.getCategory(RootCategories.Links).getString(Links.login)+"</a>");
} else {
page = page.replace("<replace id=\"1\"/>","<a href=\"logout/\" class=\"authLink\">"+langFile.getCategory(RootCategories.Links).getString(Links.logout)+"</a><br>" +
"<a href=\"cp\" class=\"authLink\">"+langFile.getCategory(RootCategories.Links).getString(Links.controlPanel)+"</a>");
}
return NanoHTTPD.newFixedLengthResponse(page);
} }
} }

View File

@ -3,10 +3,11 @@ package ru.redguy.webinfomod.pages.auth;
import fi.iki.elonen.NanoHTTPD; import fi.iki.elonen.NanoHTTPD;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import ru.redguy.webinfomod.*; import ru.redguy.webinfomod.*;
import ru.redguy.webinfomod.langs.LangFile; import ru.redguy.webinfomod.langs.Localization;
import ru.redguy.webinfomod.langs.enums.RootCategories; import ru.redguy.webinfomod.langs.enums.RootCategories;
import ru.redguy.webinfomod.langs.enums.Titles; import ru.redguy.webinfomod.langs.enums.Titles;
import ru.redguy.webinfomod.langs.enums.Words; import ru.redguy.webinfomod.langs.enums.Words;
import ru.redguy.webinfomod.utils.PlaceholdersUtils;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
@ -14,12 +15,9 @@ import java.nio.charset.Charset;
@WebPage(url = "/auth/") @WebPage(url = "/auth/")
public class Index implements IWebPage { public class Index implements IWebPage {
public NanoHTTPD.Response getPage(Config config, LangFile langFile, NanoHTTPD.IHTTPSession session) throws IOException { public NanoHTTPD.Response getPage(Config config, NanoHTTPD.IHTTPSession session) throws IOException {
String path = "/resources/web/pages/auth/Index.html"; String path = "/resources/web/auth/index.html";
String page = IOUtils.toString(WebServer.class.getResourceAsStream(path), Charset.defaultCharset()); String page = IOUtils.toString(WebServer.class.getResourceAsStream(path), Charset.defaultCharset());
page = page.replace("<replace id=\"1\"/>",langFile.getCategory(RootCategories.Titles).getString(Titles.authPage)); return NanoHTTPD.newFixedLengthResponse(new PlaceholdersUtils(session).work(page));
page = page.replace("<replace id=\"2\"/>",langFile.getCategory(RootCategories.Words).getString(Words.user));
page = page.replace("<replace id=\"3\"/>",langFile.getCategory(RootCategories.Words).getString(Words.password));
return NanoHTTPD.newFixedLengthResponse(page);
} }
} }

View File

@ -2,7 +2,7 @@ package ru.redguy.webinfomod.pages.auth;
import fi.iki.elonen.NanoHTTPD; import fi.iki.elonen.NanoHTTPD;
import ru.redguy.webinfomod.*; import ru.redguy.webinfomod.*;
import ru.redguy.webinfomod.langs.LangFile; import ru.redguy.webinfomod.langs.Localization;
import ru.redguy.webinfomod.utils.WebUtils; import ru.redguy.webinfomod.utils.WebUtils;
import java.io.IOException; import java.io.IOException;
@ -13,7 +13,7 @@ import java.util.Map;
@WebPage(url = "/auth/worker/") @WebPage(url = "/auth/worker/")
public class Worker implements IWebPage { public class Worker implements IWebPage {
public NanoHTTPD.Response getPage(Config config, LangFile langFile, NanoHTTPD.IHTTPSession session) throws IOException { public NanoHTTPD.Response getPage(Config config, NanoHTTPD.IHTTPSession session) throws IOException {
try { try {
session.parseBody(new HashMap<String, String>()); session.parseBody(new HashMap<String, String>());
} catch (NanoHTTPD.ResponseException e) { } catch (NanoHTTPD.ResponseException e) {

View File

@ -6,9 +6,10 @@ import ru.redguy.webinfomod.Config;
import ru.redguy.webinfomod.IWebPage; import ru.redguy.webinfomod.IWebPage;
import ru.redguy.webinfomod.WebPage; import ru.redguy.webinfomod.WebPage;
import ru.redguy.webinfomod.WebServer; import ru.redguy.webinfomod.WebServer;
import ru.redguy.webinfomod.langs.LangFile; import ru.redguy.webinfomod.langs.Localization;
import ru.redguy.webinfomod.langs.enums.Links; import ru.redguy.webinfomod.langs.enums.Links;
import ru.redguy.webinfomod.langs.enums.RootCategories; import ru.redguy.webinfomod.langs.enums.RootCategories;
import ru.redguy.webinfomod.utils.PlaceholdersUtils;
import ru.redguy.webinfomod.utils.WebUtils; import ru.redguy.webinfomod.utils.WebUtils;
import java.io.IOException; import java.io.IOException;
@ -16,16 +17,9 @@ import java.nio.charset.StandardCharsets;
@WebPage(url = "/cp/") @WebPage(url = "/cp/")
public class Index implements IWebPage { public class Index implements IWebPage {
public NanoHTTPD.Response getPage(Config config, LangFile langFile, NanoHTTPD.IHTTPSession session) throws IOException { public NanoHTTPD.Response getPage(Config config, NanoHTTPD.IHTTPSession session) throws IOException {
String path = "/resources/web/pages/cp/index.html"; String path = "/resources/web/cp/index.html";
String page = IOUtils.toString(WebServer.class.getResourceAsStream(path), StandardCharsets.UTF_8); String page = IOUtils.toString(WebServer.class.getResourceAsStream(path), StandardCharsets.UTF_8);
WebUtils.CookieHandler ch = new WebUtils.CookieHandler(session.getHeaders()); return NanoHTTPD.newFixedLengthResponse(new PlaceholdersUtils(session).work(page));
if(ch.read("session") == null) {
page = page.replace("<replace id=\"1\"/>","<a href=\"auth/\" class=\"authLink\">"+langFile.getCategory(RootCategories.Links).getString(Links.login)+"</a>");
} else {
page = page.replace("<replace id=\"1\"/>","<a href=\"logout/\" class=\"authLink\">"+langFile.getCategory(RootCategories.Links).getString(Links.logout)+"</a><br>" +
"<a href=\"cp/\" class=\"authLink\">"+langFile.getCategory(RootCategories.Links).getString(Links.controlPanel)+"</a>");
}
return NanoHTTPD.newFixedLengthResponse(page);
} }
} }

View File

@ -3,7 +3,7 @@ package ru.redguy.webinfomod.pages.json;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import fi.iki.elonen.NanoHTTPD; import fi.iki.elonen.NanoHTTPD;
import ru.redguy.webinfomod.*; import ru.redguy.webinfomod.*;
import ru.redguy.webinfomod.langs.LangFile; import ru.redguy.webinfomod.langs.Localization;
import ru.redguy.webinfomod.utils.DataUtils; import ru.redguy.webinfomod.utils.DataUtils;
import java.io.IOException; import java.io.IOException;
@ -11,7 +11,7 @@ import java.io.IOException;
@WebPage(url="/json/mainData.json") @WebPage(url="/json/mainData.json")
public class MainData implements IWebPage { public class MainData implements IWebPage {
public NanoHTTPD.Response getPage(Config config, LangFile langFile, NanoHTTPD.IHTTPSession session) throws IOException { public NanoHTTPD.Response getPage(Config config, NanoHTTPD.IHTTPSession session) throws IOException {
JsonObject jsonObject = new JsonObject(); JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("MineV",config.getString("MineV")); jsonObject.addProperty("MineV",config.getString("MineV"));
StringBuilder players = new StringBuilder(); StringBuilder players = new StringBuilder();

View File

@ -2,14 +2,14 @@ package ru.redguy.webinfomod.pages.logout;
import fi.iki.elonen.NanoHTTPD; import fi.iki.elonen.NanoHTTPD;
import ru.redguy.webinfomod.*; import ru.redguy.webinfomod.*;
import ru.redguy.webinfomod.langs.LangFile; import ru.redguy.webinfomod.langs.Localization;
import ru.redguy.webinfomod.utils.WebUtils; import ru.redguy.webinfomod.utils.WebUtils;
import java.io.IOException; import java.io.IOException;
@WebPage(url = "/logout/") @WebPage(url = "/logout/")
public class Index implements IWebPage { public class Index implements IWebPage {
public NanoHTTPD.Response getPage(Config config, LangFile langFile, NanoHTTPD.IHTTPSession session) throws IOException { public NanoHTTPD.Response getPage(Config config, NanoHTTPD.IHTTPSession session) throws IOException {
WebUtils.CookieHandler ch = new WebUtils.CookieHandler(session.getHeaders()); WebUtils.CookieHandler ch = new WebUtils.CookieHandler(session.getHeaders());
config.getLogger().info(LoggerType.Web,config.sessions.get(ch.read("session"))+ " has been logout!"); config.getLogger().info(LoggerType.Web,config.sessions.get(ch.read("session"))+ " has been logout!");
ch.delete("session"); ch.delete("session");

View File

@ -1,5 +1,5 @@
package ru.redguy.webinfomod.utils; package ru.redguy.webinfomod.utils;
public class DoerUtils { public class ActionsUtils {
} }

View File

@ -0,0 +1,40 @@
package ru.redguy.webinfomod.utils;
import ru.redguy.webinfomod.Logger;
import ru.redguy.webinfomod.langs.Localization;
import ru.redguy.webinfomod.langs.enums.Links;
import ru.redguy.webinfomod.langs.enums.RootCategories;
import java.util.Arrays;
import java.util.Objects;
public class BasePlaceholders {
public static void registerBase() {
PlaceholdersUtils.registerPlaceholder("auth", new Placeholder() {
@Override
public String getContent(String[] args, PlaceholdersUtils placeholdersUtils) {
WebUtils.CookieHandler ch = new WebUtils.CookieHandler(placeholdersUtils.getSession().getHeaders());
if(ch.read("session") == null) {
return "<a href=\"auth/\" class=\"authLink\">"+ Localization.getCategory(RootCategories.Links).getString(Links.login)+"</a>";
} else {
return "<a href=\"logout/\" class=\"authLink\">"+Localization.getCategory(RootCategories.Links).getString(Links.logout)+"</a><br>" +
"<a href=\"cp\" class=\"authLink\">"+Localization.getCategory(RootCategories.Links).getString(Links.controlPanel)+"</a>";
}
}
});
PlaceholdersUtils.registerPlaceholder("title", new Placeholder() {
@Override
public String getContent(String[] args, PlaceholdersUtils placeholdersUtils) {
return Objects.requireNonNull(Localization.getCategory(RootCategories.Titles)).getString(args[0]);
}
});
PlaceholdersUtils.registerPlaceholder("word", new Placeholder() {
@Override
public String getContent(String[] args, PlaceholdersUtils placeholdersUtils) {
return Objects.requireNonNull(Localization.getCategory(RootCategories.Words)).getString(args[0]);
}
});
}
}

View File

@ -0,0 +1,6 @@
package ru.redguy.webinfomod.utils;
public interface Placeholder {
String getContent(String[] args,PlaceholdersUtils placeholdersUtils);
}

View File

@ -0,0 +1,51 @@
package ru.redguy.webinfomod.utils;
import fi.iki.elonen.NanoHTTPD;
import java.util.Arrays;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PlaceholdersUtils {
private static final HashMap<String, Placeholder> placeholders = new HashMap<>();
public static void registerPlaceholder(String name, Placeholder placeholder) {
placeholders.put(name, placeholder);
}
Pattern pattern = Pattern.compile("\\{(\\w.+ *\\w*)}");
private final NanoHTTPD.IHTTPSession session;
public PlaceholdersUtils(NanoHTTPD.IHTTPSession session) {
this.session = session;
}
public NanoHTTPD.IHTTPSession getSession() {
return session;
}
public String work(String page) {
Matcher match = pattern.matcher(page);
while (match.find()) {
for (int i = 1; i <= match.groupCount(); i++) {
String found = match.group(i);
if (!found.equals("")) {
String placeholder = found.split(" ")[0];
if (placeholders.containsKey(placeholder)) {
String[] args = found.split(" ");
if (args.length == 1) {
args = new String[0];
} else {
args = Arrays.copyOfRange(args, 1, args.length);
}
page = page.replace("{" + found + "}", placeholders.get(placeholder).getContent(args, this));
}
}
}
}
return page;
}
}

View File

@ -15,6 +15,7 @@
"EASY": "Простая", "EASY": "Простая",
"NORMAL": "Нормальная", "NORMAL": "Нормальная",
"HARD": "Сложная" "HARD": "Сложная"
} },
"loading": "Загрузка..."
} }
} }

View File

@ -2,7 +2,7 @@
<html lang="ru"> <html lang="ru">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title><replace id="1"/></title> <title>{title auth}</title>
<style> <style>
form { form {
text-align: center; text-align: center;
@ -11,8 +11,8 @@
</head> </head>
<body> <body>
<form method="post" action="/auth/worker/"> <form method="post" action="/auth/worker/">
<label for="user"><replace id="2"/>: <input name="user" id="user" type="text"></label><br> <label for="user">{word user}: <input name="user" id="user" type="text"></label><br>
<label for="password"><replace id="3"/>: <input name="password" id="password" type="password"></label><br> <label for="password">{word password}: <input name="password" id="password" type="password"></label><br>
<input type="submit"> <input type="submit">
</form> </form>
</body> </body>

View File

@ -3,14 +3,17 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>WebInfo</title> <title>WebInfo</title>
<link rel="stylesheet" type="text/css" href="/css/index.css"> <link rel="stylesheet" type="text/css" href="/css/index.css">
</head> </head>
<body> <body>
<div class="header" id="header"> <div class="header" id="header">
Идёт загрузка... {word loading}
</div> </div>
<main> <main>
<replace id="1"/> {auth}
<table id="commands">
</table>
</main> </main>
</body> </body>
</html> </html>

View File

@ -14,14 +14,15 @@
float: right; float: right;
} }
</style> </style>
<script src="/js/utils/tables.js"></script>
<script src="/js/index.js"></script> <script src="/js/index.js"></script>
</head> </head>
<body> <body>
<div class="header" id="header"> <div class="header" id="header">
Идёт загрузка... {word loading}
</div> </div>
<main> <main>
<replace id="1"/> {auth}
<table id="stat"> <table id="stat">
</table> </table>
</main> </main>

View File

@ -20,14 +20,4 @@ function updatePageInfo() {
} }
} }
function appendLine(table,array) {
let tr = document.createElement("tr");
for (let arrayKey in array) {
let td = document.createElement("td");
td.innerText = array[arrayKey];
tr.appendChild(td);
}
table.appendChild(tr);
}
document.addEventListener("DOMContentLoaded", onload); document.addEventListener("DOMContentLoaded", onload);

View File

@ -0,0 +1,11 @@
class Tables {
static appendLine(table,array) {
let tr = document.createElement("tr");
for (let arrayKey in array) {
let td = document.createElement("td");
td.innerText = array[arrayKey];
tr.appendChild(td);
}
table.appendChild(tr);
}
}