Skip to content
This repository was archived by the owner on Aug 12, 2025. It is now read-only.

Commit 65178d0

Browse files
committed
Add backup and file management utilities with BackupHandler, DirectoryWatcher, FileCache, and FileService
1 parent 4a5c6ec commit 65178d0

2 files changed

Lines changed: 194 additions & 0 deletions

File tree

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package gg.nextforge.discord;
2+
3+
import java.util.LinkedHashMap;
4+
import java.util.Map;
5+
6+
/**
7+
* Builder for Discord embed objects.
8+
*/
9+
public class DiscordEmbedBuilder {
10+
11+
private final Map<String, Object> fields = new LinkedHashMap<>();
12+
13+
public DiscordEmbedBuilder setTitle(String title) {
14+
fields.put("title", title);
15+
return this;
16+
}
17+
18+
public DiscordEmbedBuilder setDescription(String description) {
19+
fields.put("description", description);
20+
return this;
21+
}
22+
23+
public DiscordEmbedBuilder setUrl(String url) {
24+
fields.put("url", url);
25+
return this;
26+
}
27+
28+
public DiscordEmbedBuilder setColor(int rgb) {
29+
fields.put("color", rgb);
30+
return this;
31+
}
32+
33+
public DiscordEmbedBuilder setFooter(String text, String iconUrl) {
34+
Map<String, String> footer = new LinkedHashMap<>();
35+
footer.put("text", text);
36+
if (iconUrl != null) footer.put("icon_url", iconUrl);
37+
fields.put("footer", footer);
38+
return this;
39+
}
40+
41+
public DiscordEmbedBuilder setImage(String imageUrl) {
42+
Map<String, String> image = new LinkedHashMap<>();
43+
image.put("url", imageUrl);
44+
fields.put("image", image);
45+
return this;
46+
}
47+
48+
public DiscordEmbedBuilder setThumbnail(String url) {
49+
Map<String, String> thumbnail = new LinkedHashMap<>();
50+
thumbnail.put("url", url);
51+
fields.put("thumbnail", thumbnail);
52+
return this;
53+
}
54+
55+
public DiscordEmbedBuilder setAuthor(String name, String url, String iconUrl) {
56+
Map<String, String> author = new LinkedHashMap<>();
57+
author.put("name", name);
58+
if (url != null) author.put("url", url);
59+
if (iconUrl != null) author.put("icon_url", iconUrl);
60+
fields.put("author", author);
61+
return this;
62+
}
63+
64+
public String build() {
65+
StringBuilder sb = new StringBuilder();
66+
sb.append("{");
67+
68+
boolean first = true;
69+
for (Map.Entry<String, Object> entry : fields.entrySet()) {
70+
if (!first) sb.append(",");
71+
sb.append("\"").append(entry.getKey()).append("\":");
72+
sb.append(toJson(entry.getValue()));
73+
first = false;
74+
}
75+
76+
sb.append("}");
77+
return sb.toString();
78+
}
79+
80+
@SuppressWarnings("unchecked")
81+
private String toJson(Object value) {
82+
if (value instanceof String) {
83+
return "\"" + escape((String) value) + "\"";
84+
} else if (value instanceof Map) {
85+
StringBuilder sb = new StringBuilder("{");
86+
boolean first = true;
87+
for (Map.Entry<String, String> entry : ((Map<String, String>) value).entrySet()) {
88+
if (!first) sb.append(",");
89+
sb.append("\"").append(entry.getKey()).append("\":\"").append(escape(entry.getValue())).append("\"");
90+
first = false;
91+
}
92+
sb.append("}");
93+
return sb.toString();
94+
} else {
95+
return String.valueOf(value);
96+
}
97+
}
98+
99+
private String escape(String input) {
100+
return input.replace("\"", "\\\"").replace("\n", "\\n");
101+
}
102+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package gg.nextforge.discord;
2+
3+
import java.io.OutputStream;
4+
import java.net.HttpURLConnection;
5+
import java.net.URL;
6+
import java.nio.charset.StandardCharsets;
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
import java.util.logging.Level;
10+
import java.util.logging.Logger;
11+
12+
/**
13+
* A simple Discord webhook sender with message builder support.
14+
*/
15+
public class DiscordWebhookSender {
16+
17+
private static final Logger LOGGER = Logger.getLogger("DiscordWebhookSender");
18+
19+
private final String webhookUrl;
20+
21+
public DiscordWebhookSender(String webhookUrl) {
22+
this.webhookUrl = webhookUrl;
23+
}
24+
25+
public void send(DiscordMessage message) {
26+
sendPayload(message.toJson());
27+
}
28+
29+
private void sendPayload(String json) {
30+
try {
31+
URL url = new URL(webhookUrl);
32+
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
33+
34+
connection.setRequestMethod("POST");
35+
connection.setRequestProperty("Content-Type", "application/json");
36+
connection.setDoOutput(true);
37+
38+
try (OutputStream os = connection.getOutputStream()) {
39+
os.write(json.getBytes(StandardCharsets.UTF_8));
40+
}
41+
42+
int responseCode = connection.getResponseCode();
43+
if (responseCode != HttpURLConnection.HTTP_NO_CONTENT && responseCode != HttpURLConnection.HTTP_OK) {
44+
LOGGER.warning("Discord webhook failed with response code: " + responseCode);
45+
}
46+
} catch (Exception e) {
47+
LOGGER.log(Level.SEVERE, "Failed to send Discord webhook", e);
48+
}
49+
}
50+
51+
// Builder class for messages
52+
public static class DiscordMessage {
53+
private String content;
54+
private final List<String> embeds = new ArrayList<>();
55+
56+
public DiscordMessage setContent(String content) {
57+
this.content = content;
58+
return this;
59+
}
60+
61+
public DiscordMessage addEmbed(String embedJson) {
62+
this.embeds.add(embedJson);
63+
return this;
64+
}
65+
66+
public String toJson() {
67+
StringBuilder builder = new StringBuilder();
68+
builder.append("{");
69+
70+
if (content != null) {
71+
builder.append("\"content\":\"").append(escape(content)).append("\"");
72+
}
73+
74+
if (!embeds.isEmpty()) {
75+
if (content != null) builder.append(",");
76+
builder.append("\"embeds\":[");
77+
for (int i = 0; i < embeds.size(); i++) {
78+
builder.append(embeds.get(i));
79+
if (i < embeds.size() - 1) builder.append(",");
80+
}
81+
builder.append("]");
82+
}
83+
84+
builder.append("}");
85+
return builder.toString();
86+
}
87+
88+
private String escape(String input) {
89+
return input.replace("\"", "\\\"").replace("\n", "\\n");
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)