package com.alttd.webinterface.http; import com.alttd.webinterface.web_interact.FileDownloadService; import io.javalin.Javalin; import io.javalin.http.Context; import io.javalin.http.HttpStatus; import lombok.extern.slf4j.Slf4j; import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; /** * HTTP server that exposes the /notify/.json endpoint. */ @Slf4j public class NotificationServer { private final int port; private Javalin app; /** * Creates a new NotificationServer that listens on the specified port. * * @param port The port to listen on */ public NotificationServer(int port) { this.port = port; } /** * Starts the server. */ public void startServer() { try { app = Javalin.create(config -> { config.showJavalinBanner = false; }).start(port); app.get("/notify/{file}.json", this::handleNotifyRequest); app.get("/notify/{uuid}/{file}.json", this::handleNotifyRequestUuid); log.info("NotificationServer started on port {}", port); } catch (Exception e) { log.error("Failed to start NotificationServer", e); } } /** * Stops the server. */ public void stopServer() { if (app != null) { app.stop(); log.info("NotificationServer stopped"); } } /** * Handles requests to the /notify/.json endpoint. */ private void handleNotifyRequest(Context ctx) { String uri = ctx.path(); log.info("Received download request: {} {}", ctx.method(), uri); String fileName = ctx.pathParam("file") + ".json"; log.info("Requested file: {}", fileName); CompletableFuture> optionalCompletableFuture = FileDownloadService.downloadFileAsync(fileName); downloadFile(ctx, optionalCompletableFuture); } /** * Handles requests to the /notify/.json endpoint. */ private void handleNotifyRequestUuid(Context ctx) { String uri = ctx.path(); log.info("Received UUID request: {} {}", ctx.method(), uri); String stringUUID = ctx.pathParam("uuid"); log.info("Requested uuid: {}", stringUUID); UUID uuid; try { uuid = UUID.fromString(stringUUID); } catch (Exception e) { log.error("Invalid UUID: {}", stringUUID, e); ctx.status(HttpStatus.BAD_REQUEST); ctx.contentType("text/plain"); ctx.result("Invalid UUID format"); return; } String fileName = ctx.pathParam("file") + ".json"; log.info("Requested uuid file: {}", fileName); CompletableFuture> optionalCompletableFuture = FileDownloadService.downloadFileAsync(uuid, fileName); downloadFile(ctx, optionalCompletableFuture); } private void downloadFile(Context ctx, CompletableFuture> optionalCompletableFuture) { optionalCompletableFuture.thenAccept(fileData -> { if (fileData.isPresent()) { ctx.contentType("application/json"); ctx.result(fileData.get()); } else { ctx.status(HttpStatus.NOT_FOUND); ctx.contentType("text/plain"); ctx.result("File not found or download failed"); } }).exceptionally(e -> { log.error("Error downloading file", e); ctx.status(HttpStatus.INTERNAL_SERVER_ERROR); ctx.contentType("text/plain"); ctx.result("Failed to handle download"); return null; }); } }