style: remove claude comments
/ build (push) Successful in 15s
/ build-docker-nightly (push) Successful in 35s
/ build-docker-release (push) Has been skipped

This commit is contained in:
2026-04-29 00:27:21 +02:00
parent efef03a5fa
commit de437fd914
5 changed files with 0 additions and 84 deletions
-20
View File
@@ -4,26 +4,9 @@ services:
restart: unless-stopped
ports:
- "8080:8080"
volumes:
# Mount your custom config here — overrides the defaults inside the image
- ./config:/app/config:ro
environment:
# Optional: override the port
- LOG_LEVEL=debug
- SERVER_PORT=8080
networks:
- seerr-net
# ── Jellyseerr (local test instance) ─────────────────────────────────────
# Access the UI at: http://localhost:5055
#
# After first start, go through the setup wizard. When asked for a media
# server you can skip it or point to a local Jellyfin (see below).
#
# Webhook setup in Jellyseerr:
# Settings → Notifications → Webhook
# URL: http://webhook-proxy:8080/webhook ← uses the internal Docker hostname
# Payload: leave as default
seerr:
image: seerr/seerr:latest
container_name: seerr
@@ -36,9 +19,6 @@ services:
networks:
- seerr-net
# ── Jellyfin (optional — only needed if Jellyseerr asks for a media server)
# Access the UI at: http://localhost:8096
# Remove this block if you don't want a full media server locally.
jellyfin:
image: jellyfin/jellyfin:latest
container_name: jellyfin
@@ -4,19 +4,13 @@ import lombok.*;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Data
@Component
@ConfigurationProperties(prefix = "proxy")
public class ProxyConfig {
/**
* Map of notification_type → list of Discord webhook URLs.
* Use the key "default" to catch all unmatched notification types.
*/
private List<String> routes = List.of();
private Filters filters;
@@ -9,12 +9,6 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
/**
* Receives incoming Overseerr webhook POST requests and
* delegates forwarding to {@link DiscordForwardingService}.
*
* Endpoint: POST /webhook
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@@ -24,10 +18,6 @@ public class WebhookController {
private final ObjectMapper objectMapper;
private final ProxyConfig proxyConfig;
/**
* Main webhook endpoint.
* Overseerr should be configured to POST to: http://<your-host>:<port>/webhook
*/
@PostMapping("/webhook")
public ResponseEntity<String> receiveWebhook(@RequestBody String rawBody) {
log.info("Received webhook payload: {}", rawBody);
@@ -51,17 +41,8 @@ public class WebhookController {
}
}
// Forward asynchronously — we return 200 immediately to Overseerr
forwardingService.forward(payload, rawBody);
return ResponseEntity.ok("OK");
}
/**
* Simple health / test endpoint.
*/
@GetMapping("/health")
public ResponseEntity<String> health() {
return ResponseEntity.ok("Webhook proxy is running.");
}
}
@@ -23,10 +23,7 @@ public class SeerrPayload {
/** Media overview / synopsis, or issue description. */
private String message;
/** URL to the media poster image. */
private String image;
private Media media;
private Request request;
private Issue issue;
@@ -39,14 +36,9 @@ public class SeerrPayload {
@JsonProperty("media_type")
private String mediaType;
private String tmdbId;
private String tvdbId;
/** Availability status: UNKNOWN | PENDING | PROCESSING | PARTIALLY_AVAILABLE | AVAILABLE */
private String status;
/** 4K availability status (same values as status). */
private String status4k;
}
@@ -80,11 +72,9 @@ public class SeerrPayload {
@JsonProperty("issue_id")
private String issueId;
/** VIDEO | AUDIO | SUBTITLES | OTHER */
@JsonProperty("issue_type")
private String issueType;
/** OPEN | IN_PROGRESS | RESOLVED */
@JsonProperty("issue_status")
private String issueStatus;
@@ -18,10 +18,6 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
/**
* Builds a Discord embed message from the Overseerr payload
* and forwards it concurrently to all configured webhook URLs.
*/
@Slf4j
@Service
@RequiredArgsConstructor
@@ -34,12 +30,6 @@ public class DiscordForwardingService {
.connectTimeout(Duration.ofSeconds(5))
.build();
/**
* Forwards the payload to all Discord webhooks matching the notification type.
*
* @param payload the parsed Overseerr payload
* @param rawBody the original raw JSON body (used as fallback)
*/
public void forward(SeerrPayload payload, String rawBody) {
String mediaName = payload.getSubject();
List<String> targets = proxyConfig.getRoutes();
@@ -53,20 +43,14 @@ public class DiscordForwardingService {
String discordBody = buildDiscordPayload(payload);
// Fire all requests concurrently
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (String webhookUrl : targets) {
futures.add(sendAsync(webhookUrl, discordBody, mediaName));
}
// Wait for all to complete (best-effort, errors are logged but not re-thrown)
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
}
// -------------------------------------------------------------------------
// Internal helpers
// -------------------------------------------------------------------------
private CompletableFuture<Void> sendAsync(String webhookUrl, String body, String notificationType) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(webhookUrl))
@@ -92,10 +76,6 @@ public class DiscordForwardingService {
});
}
/**
* Builds a Discord-compatible JSON payload with an embed.
* Discord webhooks expect: { "embeds": [ { "title": "...", ... } ] }
*/
private String buildDiscordPayload(SeerrPayload payload) {
try {
int color = colorForType(payload.getNotificationType());
@@ -110,7 +90,6 @@ public class DiscordForwardingService {
embed.put("thumbnail", Map.of("url", payload.getImage()));
}
// Field: requested by
List<Map<String, Object>> fields = new ArrayList<>();
if (payload.getRequest() != null && payload.getRequest().getRequestedByUsername() != null) {
fields.add(field("Requested by", payload.getRequest().getRequestedByUsername(), true));
@@ -153,9 +132,6 @@ public class DiscordForwardingService {
return Map.of("name", name, "value", value, "inline", inline);
}
/**
* Returns a Discord embed color (decimal) based on the notification type.
*/
private int colorForType(String type) {
if (type == null) return 0x95A5A6; // grey
return switch (type) {
@@ -166,11 +142,6 @@ public class DiscordForwardingService {
};
}
/**
* Masks the webhook token in the URL for safe logging.
* Input: https://discord.com/api/webhooks/1234567890/AbCdEfGhIj...
* Output: https://discord.com/api/webhooks/1234567890/Ab***
*/
private String maskUrl(String url) {
int lastSlash = url.lastIndexOf('/');
if (lastSlash < 0 || lastSlash >= url.length() - 1) return url;