Skip to content

Instantly share code, notes, and snippets.

@lenis0012
Last active June 30, 2016 21:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lenis0012/1f06e861e6210544e6d58c23d5c3b021 to your computer and use it in GitHub Desktop.
Save lenis0012/1f06e861e6210544e6d58c23d5c3b021 to your computer and use it in GitHub Desktop.
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.*;
import com.google.gson.stream.JsonWriter;
import lombok.SneakyThrows;
import org.apache.commons.codec.binary.Hex;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.StoredConfig;
import spark.Request;
import spark.Response;
import java.io.*;
import java.security.MessageDigest;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import static spark.Spark.*;
public class TranslationAPI {
private static final String CLONE_URL = "https://github.com/lenis0012/Translations.git";
private static Gson gson;
public static void main(String[] args) {
TranslationAPI api = new TranslationAPI();
gson = new GsonBuilder()
.setPrettyPrinting()
.create();
port(9091);
get("/list", api::list, gson::toJson);
get("/language/:code", api::language, gson::toJson);
get("/update/:key", api::update, gson::toJson);
}
private final List<Translation> translations = Lists.newArrayList();
private final Map<String, JsonObject> dataMap = Maps.newConcurrentMap();
private final JsonParser jsonParser = new JsonParser();
private final ReadWriteLock lock = new ReentrantReadWriteLock();
public TranslationAPI() {
refresh();
}
public Object language(Request req, Response res) {
res.type("application/json; charset=utf-8");
JsonObject body = new JsonObject();
lock.readLock().lock();
JsonObject data = dataMap.get(req.params(":code"));
lock.readLock().unlock();
if(data == null) {
body = new JsonObject();
body.addProperty("success", false);
body.addProperty("error", "Invalid language code!");
return body;
}
body.addProperty("success", true);
body.add("data", data);
return body;
}
public Object list(Request req, Response res) {
res.type("application/json; charset=utf-8");
JsonObject body = new JsonObject();
lock.readLock().lock();
JsonArray translations = new JsonArray();
for(Translation translation : this.translations) {
JsonObject json = new JsonObject();
json.addProperty("code", translation.getCode());
json.addProperty("localizedName", translation.getName());
json.addProperty("authors", translation.getAuthors());
json.addProperty("pluginVersion", translation.getPluginVersion());
json.addProperty("updatedAt", translation.getUpdatedAt().getTime());
translations.add(json);
}
lock.readLock().unlock();
body.addProperty("success", true);
body.add("languages", translations);
return body;
}
public Object update(Request req, Response res) {
res.type("application/json");
final String key = req.params(":key");
if(key == null || !key.equals("{project.securityKey}")) {
JsonObject json = new JsonObject();
json.addProperty("success", false);
json.addProperty("error", "Invalid key!");
return json;
}
// Clear
System.out.println("Clearing target...");
File target = new File("repo");
target.mkdir();
delete(target);
// Clone
System.out.println("Cloning repository...");
try {
Git result = Git.cloneRepository().setURI(CLONE_URL).setDirectory(target).call();
try {
StoredConfig config = result.getRepository().getConfig();
config.setBoolean("core", null, "autocrlf", true);
config.save();
} finally {
result.close();
}
} catch(Exception e) {
System.err.println("Couldn't clone repo!");
e.printStackTrace();
}
// Generate times
File timesFile = new File("times.json");
File hashesFile = new File("hashes.json");
JsonObject times = jsonFromFile(timesFile);
JsonObject hashes = jsonFromFile(hashesFile);
for(File file : target.listFiles()) {
if(!file.getName().endsWith(".json")) continue;
String code = file.getName().split("\\.")[0];
String hash = sha1sum(file);
if(!hashes.has(code)) {
System.out.println("New hash for " + code + ": " + hash);
hashes.addProperty(code, hash);
times.addProperty(code, System.currentTimeMillis());
} else if(!hash.equals(hashes.get(code).getAsString())) {
System.out.println("Updated hash for " + code + ": " + hash);
hashes.addProperty(code, hash);
times.addProperty(code, System.currentTimeMillis());
}
}
jsonToFile(timesFile, times);
jsonToFile(hashesFile, hashes);
// Refresh
System.out.println("Refreshing references...");
refresh();
System.out.println("Done!");
JsonObject json = new JsonObject();
json.addProperty("success", true);
return json;
}
private void delete(File file) {
if(file.isDirectory()) {
for(File f : file.listFiles()) {
delete(f);
}
}
while(!file.delete());
}
private void refresh() {
lock.writeLock().lock();
translations.clear();
File dir = new File("repo");
if(!dir.exists() || !dir.isDirectory()) {
lock.writeLock().unlock();
return;
}
File timesFile = new File("times.json");
JsonObject times = jsonFromFile(timesFile);
for(File file : dir.listFiles()) {
if(!file.getName().endsWith(".json")) continue;
String code = file.getName().split("\\.")[0];
try {
JsonObject json = jsonFromFile(file);
long updatedAt = times.has(code) ? times.get(code).getAsLong() : System.currentTimeMillis();
json.addProperty("updatedAt", updatedAt);
json.addProperty("code", code);
translations.add(new Translation(json));
dataMap.put(code, json);
} catch(Exception e) {
System.err.println("Error while loading language " + code);
e.printStackTrace();
}
}
Collections.sort(translations, (t1, t2) -> t1.getName().compareTo(t2.getName()));
lock.writeLock().unlock();
}
@SneakyThrows
private JsonObject jsonFromFile(File file) {
if(!file.exists()) {
return new JsonObject();
}
FileReader reader = new FileReader(file);
JsonObject json = jsonParser.parse(reader).getAsJsonObject();
reader.close();
return json;
}
@SneakyThrows
private void jsonToFile(File file, JsonObject json) {
JsonWriter writer = gson.newJsonWriter(new FileWriter(file));
gson.toJson(json, writer);
writer.flush();
writer.close();
}
@SneakyThrows
private String sha1sum(File file) {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.reset();
FileInputStream input = null;
try {
input = new FileInputStream(file);
byte[] buffer = new byte[1024];
int length;
while ((length = input.read(buffer)) != -1) {
digest.update(buffer, 0, length);
}
} catch(Exception e) {
System.err.println("Failed to create hash");
e.printStackTrace();
} finally {
if(input != null) {
try {
input.close();
} catch(IOException e) {}
}
}
return Hex.encodeHexString(digest.digest());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment