mirror of
https://github.com/demodude4u/Factorio-FBSR.git
synced 2025-01-11 18:24:27 +02:00
Added upload database to remember URLs and recall
This commit is contained in:
parent
5845a390e8
commit
d8c27dd9f0
@ -81,11 +81,6 @@
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.pircbotx</groupId>
|
||||
<artifactId>pircbotx</artifactId>
|
||||
<version>2.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
@ -96,5 +91,10 @@
|
||||
<artifactId>jaxb-api</artifactId>
|
||||
<version>2.2.11</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dizitart</groupId>
|
||||
<artifactId>nitrite</artifactId>
|
||||
<version>3.4.4</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
@ -59,7 +59,10 @@ public class BlueprintStringData {
|
||||
private final Optional<String> label;
|
||||
private final MapVersion version;
|
||||
|
||||
private final String blueprintStringRaw;
|
||||
|
||||
public BlueprintStringData(String blueprintString) throws IllegalArgumentException, IOException {
|
||||
this.blueprintStringRaw = blueprintString;
|
||||
String versionChar = blueprintString.substring(0, 1);
|
||||
try {
|
||||
if (Integer.parseInt(versionChar) != 0) {
|
||||
@ -138,4 +141,9 @@ public class BlueprintStringData {
|
||||
public JSONObject json() {
|
||||
return json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return blueprintStringRaw;
|
||||
}
|
||||
}
|
||||
|
@ -1,37 +1,40 @@
|
||||
package com.demod.fbsr;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.dizitart.no2.Document;
|
||||
import org.dizitart.no2.IndexOptions;
|
||||
import org.dizitart.no2.IndexType;
|
||||
import org.dizitart.no2.Nitrite;
|
||||
import org.dizitart.no2.NitriteCollection;
|
||||
import org.dizitart.no2.filters.Filters;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import com.demod.factorio.Utils;
|
||||
import com.demod.fbsr.app.BlueprintBotDiscordService;
|
||||
import com.demod.fbsr.app.ServiceFinder;
|
||||
import com.google.common.util.concurrent.Uninterruptibles;
|
||||
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
|
||||
public final class WebUtils {
|
||||
private static Nitrite db = initializeDatabase();
|
||||
private static NitriteCollection dbUploads = db.getCollection("uploads");
|
||||
|
||||
public static void addPossiblyLargeEmbedField(EmbedBuilder builder, String name, String value, boolean inline)
|
||||
throws IOException {
|
||||
if (value.length() <= MessageEmbed.VALUE_MAX_LENGTH) {
|
||||
@ -42,6 +45,35 @@ public final class WebUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private static void addToUploadedDatabase(String fileHash, String url) {
|
||||
dbUploads.insert(Document.createDocument("hash", fileHash).put("url", url));
|
||||
}
|
||||
|
||||
private static Optional<String> checkIfUploadedAlready(String fileHash) {
|
||||
return Optional.ofNullable(dbUploads.find(Filters.eq("hash", fileHash)).firstOrDefault())
|
||||
.flatMap(d -> Optional.ofNullable(d.get("url").toString()));
|
||||
}
|
||||
|
||||
private static byte[] generateDiscordFriendlyPNGImage(BufferedImage image) {
|
||||
byte[] imageData = WebUtils.getImageData(image);
|
||||
|
||||
while (imageData.length > Message.MAX_FILE_SIZE) {
|
||||
image = RenderUtils.scaleImage(image, image.getWidth() / 2, image.getHeight() / 2);
|
||||
imageData = WebUtils.getImageData(image);
|
||||
}
|
||||
|
||||
return imageData;
|
||||
}
|
||||
|
||||
private static String generateFileHash(byte[] fileData) {
|
||||
try {
|
||||
return Hex.encodeHexString(MessageDigest.getInstance("MD5").digest(fileData));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static byte[] getImageData(BufferedImage image) {
|
||||
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
||||
ImageIO.write(image, "PNG", baos);
|
||||
@ -52,6 +84,22 @@ public final class WebUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private static Nitrite initializeDatabase() {
|
||||
try {
|
||||
Nitrite db = Nitrite.builder().compressed().filePath("database.db").openOrCreate();
|
||||
|
||||
NitriteCollection dbUploads = db.getCollection("uploads");
|
||||
if (!dbUploads.hasIndex("hash")) {
|
||||
dbUploads.createIndex("hash", IndexOptions.indexOptions(IndexType.Unique));
|
||||
}
|
||||
|
||||
return db;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static InputStream limitMaxBytes(InputStream delegate, int maxBytes) {
|
||||
return new InputStream() {
|
||||
int byteCount = 0;
|
||||
@ -90,110 +138,31 @@ public final class WebUtils {
|
||||
return Utils.readJsonFromStream(new URL(url).openStream());
|
||||
}
|
||||
|
||||
public static URL uploadToBundly_BROKEN(String title, String description, List<Entry<URL, String>> links)
|
||||
throws IOException {
|
||||
JSONObject request = new JSONObject();
|
||||
request.put("title", title);
|
||||
request.put("desc", description);
|
||||
|
||||
JSONArray items = new JSONArray();
|
||||
for (Entry<URL, String> pair : links) {
|
||||
JSONObject item = new JSONObject();
|
||||
item.put("url", pair.getKey().toString());
|
||||
item.put("id", Long.toString(System.currentTimeMillis()));
|
||||
item.put("caption", pair.getValue());
|
||||
items.put(item);
|
||||
|
||||
// XXX Lazy approach to make sure id is unique...
|
||||
Uninterruptibles.sleepUninterruptibly(1, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
request.put("items", items);
|
||||
|
||||
URL url = new URL("http://bundly.io/createBundle");
|
||||
URLConnection connection = url.openConnection();
|
||||
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
|
||||
connection.setDoOutput(true);
|
||||
connection.getOutputStream().write(request.toString().getBytes(StandardCharsets.UTF_8));
|
||||
connection.getOutputStream().flush();
|
||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
|
||||
String line = br.readLine();
|
||||
if (line == null || line.length() > 8) {
|
||||
throw new IOException("Bundly.io returned an invalid response: " + line);
|
||||
}
|
||||
|
||||
URL resultUrl = new URL("http://bundly.io/" + line);
|
||||
HttpURLConnection resultTestConnection = (HttpURLConnection) resultUrl.openConnection();
|
||||
resultTestConnection.setRequestMethod("GET");
|
||||
resultTestConnection.connect();
|
||||
if (resultTestConnection.getResponseCode() == 500) {
|
||||
throw new IOException("Bundly.io is still broken. :(");
|
||||
}
|
||||
|
||||
return resultUrl;
|
||||
}
|
||||
public static String uploadToHostingService(String fileName, BufferedImage image) throws IOException {
|
||||
return uploadToHostingService(fileName, generateDiscordFriendlyPNGImage(image));
|
||||
}
|
||||
|
||||
public static URL uploadToHostingService(String fileName, BufferedImage image) throws IOException {
|
||||
public static String uploadToHostingService(String fileName, byte[] fileData) throws IOException {
|
||||
String fileHash = generateFileHash(fileData);
|
||||
|
||||
Optional<String> alreadyUploaded = checkIfUploadedAlready(fileHash);
|
||||
|
||||
if (alreadyUploaded.isPresent()) {
|
||||
return alreadyUploaded.get();
|
||||
}
|
||||
|
||||
Optional<BlueprintBotDiscordService> discordService = ServiceFinder
|
||||
.findService(BlueprintBotDiscordService.class);
|
||||
|
||||
if (discordService.isPresent()) {
|
||||
// Discord original -> image hosting -> Discord scaled
|
||||
try {
|
||||
return discordService.get().useDiscordForImageHosting(fileName, image, false);
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
return uploadToRemoteHosting(fileName, getImageData(image));
|
||||
} catch (Exception e1) {
|
||||
return discordService.get().useDiscordForImageHosting(fileName, image, true);
|
||||
}
|
||||
String url = discordService.get().useDiscordForFileHosting(fileName, fileData).toString();
|
||||
addToUploadedDatabase(fileHash, url);
|
||||
return url;
|
||||
} catch (Exception e2) {
|
||||
throw new IOException("File hosting failed!", e2);
|
||||
}
|
||||
} else {
|
||||
return uploadToRemoteHosting(fileName, getImageData(image));
|
||||
}
|
||||
}
|
||||
|
||||
public static URL uploadToHostingService(String fileName, byte[] fileData) throws IOException {
|
||||
try {
|
||||
return uploadToRemoteHosting(fileName, fileData);
|
||||
} catch (Exception e) {
|
||||
Optional<BlueprintBotDiscordService> discordService = ServiceFinder
|
||||
.findService(BlueprintBotDiscordService.class);
|
||||
if (discordService.isPresent()) {
|
||||
try {
|
||||
return discordService.get().useDiscordForFileHosting(fileName, fileData);
|
||||
} catch (Exception e2) {
|
||||
throw new IOException("File hosting failed!", e2);
|
||||
}
|
||||
}
|
||||
throw new IOException("File hosting failed!");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static URL uploadToMixtapeMoe_BROKEN(String fileName, byte[] fileData) throws IOException {
|
||||
try (ByteArrayInputStream bais = new ByteArrayInputStream(fileData)) {
|
||||
MultipartUtility utility = new MultipartUtility("https://mixtape.moe/upload.php", "UTF-8");
|
||||
utility.addFormField("name", fileName);
|
||||
utility.addFilePart("files[]", fileName, bais);
|
||||
return new URL(
|
||||
new JSONObject(utility.finish().get(0)).getJSONArray("files").getJSONObject(0).getString("url"));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static URL uploadToNyaIs_BROKEN(String fileName, byte[] fileData) throws IOException {
|
||||
try (ByteArrayInputStream bais = new ByteArrayInputStream(fileData)) {
|
||||
MultipartUtility utility = new MultipartUtility("https://nya.is/upload", "UTF-8");
|
||||
utility.addFormField("name", fileName);
|
||||
utility.addFilePart("files[]", fileName, bais);
|
||||
return new URL(
|
||||
new JSONObject(utility.finish().get(0)).getJSONArray("files").getJSONObject(0).getString("url"));
|
||||
}
|
||||
}
|
||||
|
||||
private static URL uploadToRemoteHosting(String fileName, byte[] fileData) throws IOException {
|
||||
throw new IOException("No Image Host available!");// FIXME
|
||||
throw new IOException("File hosting failed! (Discord not available)");
|
||||
}
|
||||
|
||||
private WebUtils() {
|
||||
|
@ -152,15 +152,6 @@ public class BlueprintBotDiscordService extends AbstractIdleService {
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] generateDiscordFriendlyPNGImage(BufferedImage image) {
|
||||
byte[] imageData = WebUtils.getImageData(image);
|
||||
if (imageData.length > 8000000) {
|
||||
return generateDiscordFriendlyPNGImage(
|
||||
RenderUtils.scaleImage(image, image.getWidth() / 2, image.getHeight() / 2));
|
||||
}
|
||||
return imageData;
|
||||
}
|
||||
|
||||
public DiscordBot getBot() {
|
||||
return bot;
|
||||
}
|
||||
@ -235,12 +226,12 @@ public class BlueprintBotDiscordService extends AbstractIdleService {
|
||||
|
||||
List<Blueprint> blueprints = blueprintStringDatas.stream().flatMap(bs -> bs.getBlueprints().stream())
|
||||
.collect(Collectors.toList());
|
||||
List<Entry<URL, String>> links = new ArrayList<>();
|
||||
List<Entry<String, String>> links = new ArrayList<>();
|
||||
for (Blueprint blueprint : blueprints) {
|
||||
try {
|
||||
blueprint.json().remove("index");
|
||||
|
||||
URL url = WebUtils.uploadToHostingService("blueprint.txt",
|
||||
String url = WebUtils.uploadToHostingService("blueprint.txt",
|
||||
BlueprintStringData.encode(blueprint.json()).getBytes());
|
||||
links.add(new SimpleEntry<>(url, blueprint.getLabel().orElse(null)));
|
||||
} catch (Exception e) {
|
||||
@ -254,7 +245,7 @@ public class BlueprintBotDiscordService extends AbstractIdleService {
|
||||
ArrayDeque<String> lines = links.stream()
|
||||
.map(p -> (p.getValue() != null && !p.getValue().isEmpty())
|
||||
? ("[" + p.getValue() + "](" + p.getKey() + ")")
|
||||
: p.getKey().toString())
|
||||
: p.getKey())
|
||||
.collect(Collectors.toCollection(ArrayDeque::new));
|
||||
while (!lines.isEmpty()) {
|
||||
EmbedBuilder builder = new EmbedBuilder();
|
||||
@ -584,13 +575,13 @@ public class BlueprintBotDiscordService extends AbstractIdleService {
|
||||
} else if (images.size() == 1) {
|
||||
Entry<Optional<String>, BufferedImage> entry = images.get(0);
|
||||
BufferedImage image = entry.getValue();
|
||||
URL url = WebUtils.uploadToHostingService("blueprint.png", image);
|
||||
String url = WebUtils.uploadToHostingService("blueprint.png", image);
|
||||
EmbedBuilder builder = new EmbedBuilder();
|
||||
builder.setImage(url.toString());
|
||||
builder.setImage(url);
|
||||
embedBuilders.add(builder);
|
||||
|
||||
} else {
|
||||
List<Entry<URL, String>> links = new ArrayList<>();
|
||||
List<Entry<String, String>> links = new ArrayList<>();
|
||||
for (Entry<Optional<String>, BufferedImage> entry : images) {
|
||||
BufferedImage image = entry.getValue();
|
||||
links.add(new SimpleEntry<>(WebUtils.uploadToHostingService("blueprint.png", image),
|
||||
@ -599,29 +590,46 @@ public class BlueprintBotDiscordService extends AbstractIdleService {
|
||||
|
||||
ArrayDeque<String> lines = new ArrayDeque<>();
|
||||
for (int i = 0; i < links.size(); i++) {
|
||||
Entry<URL, String> entry = links.get(i);
|
||||
Entry<String, String> entry = links.get(i);
|
||||
if (entry.getValue() != null && !entry.getValue().trim().isEmpty()) {
|
||||
lines.add("[" + entry.getValue().trim() + "](" + entry.getKey() + ")");
|
||||
} else {
|
||||
lines.add("[Blueprint " + (i + 1) + "](" + entry.getKey() + ")");
|
||||
lines.add("[Blueprint Image " + (i + 1) + "](" + entry.getKey() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
while (!lines.isEmpty()) {
|
||||
EmbedBuilder builder = new EmbedBuilder();
|
||||
StringBuilder description = new StringBuilder();
|
||||
while (!lines.isEmpty()) {
|
||||
if (description.length() + lines.peek().length() + 1 < MessageEmbed.DESCRIPTION_MAX_LENGTH) {
|
||||
description.append(lines.pop()).append('\n');
|
||||
} else {
|
||||
break;
|
||||
for (int i = 0; i < 3 && !lines.isEmpty(); i++) {
|
||||
StringBuilder description = new StringBuilder();
|
||||
while (!lines.isEmpty()) {
|
||||
if (description.length() + lines.peek().length() + 1 < MessageEmbed.VALUE_MAX_LENGTH) {
|
||||
description.append(lines.pop()).append('\n');
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
builder.addField("", description.toString(), true);
|
||||
}
|
||||
builder.setDescription(description);
|
||||
embedBuilders.add(builder);
|
||||
}
|
||||
}
|
||||
|
||||
if (!blueprintStrings.isEmpty() && !embedBuilders.isEmpty()) {
|
||||
List<String> links = new ArrayList<>();
|
||||
for (int i = 0; i < blueprintStrings.size(); i++) {
|
||||
BlueprintStringData blueprintString = blueprintStrings.get(i);
|
||||
String label = blueprintString.getLabel().orElse(
|
||||
(blueprintString.getBlueprints().size() > 1 ? "Blueprint Book " : "Blueprint ") + (i + 1));
|
||||
String link = WebUtils.uploadToHostingService("blueprint.txt", blueprintString.toString().getBytes());
|
||||
links.add("[" + label + "](" + link + ")");
|
||||
}
|
||||
|
||||
embedBuilders.get(0).getFields().add(0,
|
||||
new Field("Blueprint String" + (blueprintStrings.size() > 1 ? "s" : ""),
|
||||
links.stream().collect(Collectors.joining("\n")), false));
|
||||
}
|
||||
|
||||
return embedBuilders;
|
||||
}
|
||||
|
||||
@ -633,8 +641,8 @@ public class BlueprintBotDiscordService extends AbstractIdleService {
|
||||
json.put("version", FBSR.getVersion());
|
||||
json.put("data", Utils.<JSONObject>convertLuaToJson(lua));
|
||||
String fileName = category + "_" + name + "_dump_" + FBSR.getVersion() + ".json";
|
||||
URL url = WebUtils.uploadToHostingService(fileName, json.toString(2).getBytes());
|
||||
event.reply(category + " " + name + " lua dump: [" + fileName + "](" + url.toString() + ")");
|
||||
String url = WebUtils.uploadToHostingService(fileName, json.toString(2).getBytes());
|
||||
event.reply(category + " " + name + " lua dump: [" + fileName + "](" + url + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -848,14 +856,4 @@ public class BlueprintBotDiscordService extends AbstractIdleService {
|
||||
Message message = channel.sendFile(fileData, fileName).complete();
|
||||
return new URL(message.getAttachments().get(0).getUrl());
|
||||
}
|
||||
|
||||
public URL useDiscordForImageHosting(String fileName, BufferedImage image, boolean downscaleIfNeeded)
|
||||
throws IOException {
|
||||
TextChannel channel = bot.getJDA().getTextChannelById(hostingChannelID);
|
||||
Message message = channel
|
||||
.sendFile(downscaleIfNeeded ? generateDiscordFriendlyPNGImage(image) : WebUtils.getImageData(image),
|
||||
fileName)
|
||||
.complete();
|
||||
return new URL(message.getAttachments().get(0).getUrl());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user