Skip to content
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package org.togetherjava.tjbot.features.utils;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;

import com.linkedin.urls.Url;
import com.linkedin.urls.detection.UrlDetector;
import com.linkedin.urls.detection.UrlDetectorOptions;
Expand Down Expand Up @@ -57,6 +63,54 @@ public static List<String> extractLinks(String content, Set<LinkFilter> filter)
public static boolean containsLink(String content) {
return !(new UrlDetector(content, UrlDetectorOptions.BRACKET_MATCH).detect().isEmpty());
}
public static CompletableFuture<Boolean> isLinkBroken(String url) {
HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder(URI.create(url))
.method("HEAD", HttpRequest.BodyPublishers.noBody())
.build();

return client.sendAsync(request, HttpResponse.BodyHandlers.discarding())
.thenApply(response -> response.statusCode() >= 400)
.exceptionally(ignored -> true);
}
public static CompletableFuture<String> replaceDeadLinks(
String text,
String replacement
) {
Set<LinkFilter> filters = Set.of(
LinkFilter.SUPPRESSED,
LinkFilter.NON_HTTP_SCHEME
);

List<String> links = extractLinks(text, filters);

if (links.isEmpty()) {
return CompletableFuture.completedFuture(text);
}

StringBuilder result = new StringBuilder(text);

List<CompletableFuture<Void>> checks = links.stream()
.map(link ->
isLinkBroken(link).thenAccept(isDead -> {
if (isDead) {
int index = result.indexOf(link);
if (index != -1) {
result.replace(
index,
index + link.length(),
replacement
);
}
}
})
)
.toList();

return CompletableFuture.allOf(checks.toArray(new CompletableFuture[0]))
.thenApply(v -> result.toString());
}

private static Optional<String> toLink(Url url, Set<LinkFilter> filter) {
String raw = url.getOriginalUrl();
Expand All @@ -76,7 +130,6 @@ private static Optional<String> toLink(Url url, Set<LinkFilter> filter) {
// Remove trailing punctuation
link = link.substring(0, link.length() - 1);
}

return Optional.of(link);
}

Expand Down
Loading