Skip to content

Commit dff8665

Browse files
committed
Updated minor thingy
1 parent 1b010da commit dff8665

File tree

7 files changed

+229
-23
lines changed

7 files changed

+229
-23
lines changed

build.gradle

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ buildscript {
1717
}
1818

1919
dependencies {
20-
classpath 'org.mangorage:MangoBotGradle:6.0.10'
20+
classpath 'org.mangorage:MangoBotGradle:6.0.14'
2121
}
2222
}
2323

@@ -82,11 +82,11 @@ dependencies {
8282
testImplementation platform('org.junit:junit-bom:5.9.1')
8383
testImplementation 'org.junit.jupiter:junit-jupiter'
8484

85-
installer('org.mangorage:installer:4.0.15')
86-
bootstrap("org.mangorage:mangobotbootstrap:+")
85+
installer('org.mangorage:installer:4.0.20')
86+
bootstrap("org.mangorage:mangobotbootstrap:1.0.46")
8787

88-
plugin('org.mangorage:mangobot:12.0.63')
89-
plugin('org.mangorage:mangobotplugin:12.0.37')
88+
plugin('org.mangorage:mangobot:12.0.72')
89+
plugin('org.mangorage:mangobotplugin:12.0.41')
9090

9191
library('org.eclipse.jetty:jetty-server:11.0.16')
9292
library('org.eclipse.jetty:jetty-servlet:11.0.16')

src/main/java/module-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
requires org.jetbrains.annotations;
1212
requires net.minecraftforge.eventbus;
1313
requires net.dv8tion.jda;
14+
requires com.fasterxml.jackson.databind;
1415

1516
// Files
1617
opens templates.file;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package org.mangorage.mangobotsite;
2+
3+
import java.lang.reflect.Method;
4+
5+
public final class Helper {
6+
public static boolean isDevMode() {
7+
8+
try {
9+
final var clz = getLoadedClassFromModule(
10+
"org.mangorage.mangobotcore",
11+
"org.mangorage.entrypoint.MangoBotCore"
12+
);
13+
14+
final var method = clz.getDeclaredMethod("isDevMode");
15+
16+
return (boolean) method.invoke(Helper.class, null);
17+
} catch (Throwable e) {
18+
return false;
19+
}
20+
}
21+
22+
23+
public static Method getSimpleMethod(Class<?> clazz) {
24+
for (Method method : clazz.getDeclaredMethods()) {
25+
if (!method.isSynthetic() && !method.isBridge()) {
26+
return method;
27+
}
28+
}
29+
throw new RuntimeException("No simple method found in " + clazz.getName());
30+
}
31+
32+
public static Class<?> getLoadedClassFromModule(String moduleName, String className) {
33+
ModuleLayer bootLayer = Helper.class.getModule().getLayer();
34+
35+
return bootLayer.findModule(moduleName)
36+
.map(Module::getClassLoader)
37+
.map(loader -> {
38+
try {
39+
return Class.forName(className, false, loader); // `false` to avoid re-init
40+
} catch (ClassNotFoundException e) {
41+
throw new RuntimeException("Class not found in module: " + className, e);
42+
}
43+
})
44+
.orElseThrow(() -> new RuntimeException("Module not found: " + moduleName));
45+
}
46+
47+
}

src/main/java/org/mangorage/mangobotsite/website/WebServer.java

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.eclipse.jetty.util.ssl.SslContextFactory;
1616
import org.jetbrains.annotations.NotNull;
1717
import org.mangorage.commonutils.log.LogHelper;
18+
import org.mangorage.mangobotsite.Helper;
1819
import org.mangorage.mangobotsite.website.file.FileUploadManager;
1920
import org.mangorage.mangobotsite.website.filters.RequestInterceptorFilter;
2021
import org.mangorage.mangobotsite.website.handlers.DefaultErrorHandler;
@@ -28,6 +29,7 @@
2829
import org.mangorage.mangobotsite.website.servlet.HomeServlet;
2930
import org.mangorage.mangobotsite.website.servlet.InfoServlet;
3031
import org.mangorage.mangobotsite.website.servlet.LoginServlet;
32+
import org.mangorage.mangobotsite.website.servlet.StreamingServlet;
3133
import org.mangorage.mangobotsite.website.servlet.TestAuthServlet;
3234
import org.mangorage.mangobotsite.website.servlet.TricksServlet;
3335
import org.mangorage.mangobotsite.website.util.ResolveString;
@@ -93,7 +95,6 @@ public static void startWebServer(ObjectMap objectMap) throws Exception {
9395
// Create the ResourceHandler for resources in the JAR
9496
var file = Thread.currentThread().getContextClassLoader().getResource(WEBPAGE_INTERNAL.value());
9597
if (file == null) throw new RuntimeException("Unable to find resource directory");
96-
9798
ResourceHandler resourceHandler = new ResourceHandler();
9899
resourceHandler.setBaseResource(Resource.newResource(file));
99100

@@ -103,7 +104,6 @@ public static void startWebServer(ObjectMap objectMap) throws Exception {
103104
private static @NotNull ResourceHandler configureExternalResourceHandler() {
104105
ResourceHandler resourceHandler = new ResourceHandler();
105106
resourceHandler.setResourceBase(WEBPAGE_PAGE.value());
106-
107107
return resourceHandler;
108108
}
109109

@@ -117,7 +117,9 @@ public static void startWebServer(ObjectMap objectMap) throws Exception {
117117
.dynamic(h -> {
118118
h.setErrorHandler(new DefaultErrorHandler());
119119
})
120-
.addServlet(DefaultServlet.class, "/*")
120+
121+
.addServlet(StreamingServlet.class, "/watch")
122+
121123
.addHttpServlet(HomeServlet.class, "/home")
122124
.addHttpServlet(InfoServlet.class, "/info")
123125
.addHttpServlet(TricksServlet.class, "/trick")
@@ -149,20 +151,28 @@ public static void startWebServer(ObjectMap objectMap) throws Exception {
149151
}
150152

151153
private static @NotNull ServerConnector getServerConnector(Server server) {
152-
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
153-
sslContextFactory.setTrustAll(true);
154-
155-
sslContextFactory.setKeyStorePath(WEBPAGE_ROOT.resolveFully("keystore.jks")); // Path to your keystore
156-
sslContextFactory.setKeyStorePassword("mango12"); // Keystore password
157-
sslContextFactory.setKeyManagerPassword("mango12"); // Key manager password
158-
159-
// HTTPS Connector
160-
ServerConnector sslConnector = new ServerConnector(
161-
server,
162-
sslContextFactory
163-
);
164-
165-
sslConnector.setPort(443); // HTTPS port
166-
return sslConnector;
154+
if (!Helper.isDevMode()) {
155+
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
156+
sslContextFactory.setTrustAll(true);
157+
158+
sslContextFactory.setKeyStorePath(WEBPAGE_ROOT.resolveFully("keystore.jks")); // Path to your keystore
159+
sslContextFactory.setKeyStorePassword("mango12"); // Keystore password
160+
sslContextFactory.setKeyManagerPassword("mango12"); // Key manager password
161+
162+
// HTTPS Connector
163+
ServerConnector sslConnector = new ServerConnector(
164+
server,
165+
sslContextFactory
166+
);
167+
168+
sslConnector.setPort(1443); // HTTPS port
169+
return sslConnector;
170+
} else {
171+
ServerConnector connector = new ServerConnector(
172+
server
173+
);
174+
connector.setPort(18080);
175+
return connector;
176+
}
167177
}
168178
}

src/main/java/org/mangorage/mangobotsite/website/filters/RequestInterceptorFilter.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import jakarta.servlet.http.HttpServletResponse;
1212
import org.eclipse.jetty.server.Request;
1313
import org.mangorage.commonutils.log.LogHelper;
14+
import org.mangorage.mangobotsite.website.servlet.StreamingServlet;
1415

1516

1617
import java.io.IOException;
@@ -28,9 +29,16 @@ public void init(FilterConfig filterConfig) throws ServletException {
2829
@Override
2930
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
3031

32+
System.out.println(request.getClass());
33+
34+
3135
if (request instanceof Request main) {
3236
var ip = main.getHeader("X-Forwarded-For");
3337
LogHelper.info("Intercepted Request from %s for %s -> https://mangobot.mangorage.org%s".formatted(ip == null ? request.getRemoteAddr() : ip, main.getMethod(), main.getOriginalURI()));
38+
39+
if (main.getOriginalURI().contains("mode")) {
40+
new StreamingServlet().service(request, response);
41+
}
3442
} else if (request instanceof HttpServletRequest http) {
3543
var ip = http.getHeader("X-Forwarded-For");
3644
LogHelper.info("Unknown Type (Class) From %s -> %s".formatted(ip == null ? http.getRemoteAddr() : ip, request.getClass()));
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package org.mangorage.mangobotsite.website.servlet;
2+
3+
import jakarta.servlet.ServletException;
4+
import jakarta.servlet.http.HttpServletRequest;
5+
import jakarta.servlet.http.HttpServletResponse;
6+
import org.mangorage.mangobotsite.website.impl.StandardHttpServlet;
7+
import org.mangorage.mangobotsite.website.util.MapBuilder;
8+
9+
import java.io.File;
10+
import java.io.IOException;
11+
import java.io.OutputStream;
12+
import java.io.RandomAccessFile;
13+
import java.nio.file.Files;
14+
import java.nio.file.Path;
15+
16+
import static org.mangorage.mangobotsite.website.util.WebUtil.processTemplate;
17+
18+
19+
public class StreamingServlet extends StandardHttpServlet {
20+
21+
private final Path videoDirectory = Path.of("stream");
22+
23+
24+
25+
@Override
26+
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
27+
String videoName = req.getParameter("v");
28+
String mode = req.getParameter("mode"); // "stream" means serve bytes
29+
30+
if (videoName == null || videoName.isBlank()) {
31+
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "Missing video parameter");
32+
return;
33+
}
34+
35+
File videoFile = videoDirectory.resolve(videoName).toFile();
36+
if (!videoFile.exists() || !videoFile.isFile()) {
37+
resp.sendError(HttpServletResponse.SC_NOT_FOUND, "Video not found");
38+
return;
39+
}
40+
41+
if ("stream".equals(mode)) {
42+
System.out.println("STREAM");
43+
streamVideo(req, resp, videoFile);
44+
} else {
45+
resp.setContentType("text/html");
46+
processTemplate(
47+
MapBuilder.of()
48+
.self(this)
49+
.put("videoName", videoName)
50+
.put("title", videoFile.getName())
51+
.get(),
52+
"stream.ftl",
53+
resp.getWriter()
54+
);
55+
}
56+
}
57+
58+
private void streamVideo(HttpServletRequest req, HttpServletResponse resp, File videoFile) throws IOException {
59+
long fileLength = videoFile.length();
60+
String range = req.getHeader("Range");
61+
62+
String contentType = Files.probeContentType(videoFile.toPath());
63+
if (contentType == null) contentType = "video/mp4";
64+
65+
resp.setHeader("Accept-Ranges", "bytes");
66+
resp.setContentType(contentType);
67+
68+
try (RandomAccessFile raf = new RandomAccessFile(videoFile, "r");
69+
OutputStream out = resp.getOutputStream()) {
70+
71+
if (range != null && range.startsWith("bytes=")) {
72+
String[] parts = range.substring(6).split("-");
73+
long start = 0;
74+
long end = fileLength - 1;
75+
76+
try {
77+
start = Long.parseLong(parts[0]);
78+
if (parts.length > 1 && !parts[1].isEmpty()) {
79+
end = Long.parseLong(parts[1]);
80+
}
81+
} catch (NumberFormatException ignored) {
82+
}
83+
84+
if (start > end || start < 0 || end >= fileLength) {
85+
resp.setStatus(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
86+
resp.setHeader("Content-Range", "bytes */" + fileLength);
87+
return;
88+
}
89+
90+
long contentLength = end - start + 1;
91+
resp.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
92+
resp.setHeader("Content-Range", "bytes " + start + "-" + end + "/" + fileLength);
93+
resp.setContentLengthLong(contentLength);
94+
95+
raf.seek(start);
96+
writeStream(raf, out, contentLength);
97+
} else {
98+
resp.setContentLengthLong(fileLength);
99+
writeStream(raf, out, fileLength);
100+
}
101+
out.flush();
102+
}
103+
}
104+
105+
private void writeStream(RandomAccessFile raf, OutputStream out, long length) throws IOException {
106+
byte[] buffer = new byte[8192];
107+
long remaining = length;
108+
109+
while (remaining > 0) {
110+
int read = raf.read(buffer, 0, (int) Math.min(buffer.length, remaining));
111+
if (read == -1) break;
112+
out.write(buffer, 0, read);
113+
remaining -= read;
114+
}
115+
}
116+
117+
@Override
118+
public boolean useDefaultStyles() {
119+
return false;
120+
}
121+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>${title!"Untitled Video"}</title>
6+
<style>
7+
body { background: #000; color: #fff; text-align: center; padding: 2em; font-family: Arial, sans-serif; }
8+
video { width: 80%; max-width: 1000px; border: 2px solid #444; border-radius: 10px; background: #222; }
9+
h1 { margin-bottom: 1em; }
10+
</style>
11+
</head>
12+
<body>
13+
<h1>${title!"Untitled Video"}</h1>
14+
<video controls autoplay>
15+
<source src="/stream?v=${videoName}&mode=stream" type="video/mp4" />
16+
Your trash browser doesn’t support HTML5 video.
17+
</video>
18+
</body>
19+
</html>

0 commit comments

Comments
 (0)