MarginaliaSearch/code/features-search/screenshots/java/nu/marginalia/screenshot/ScreenshotService.java

124 lines
4.1 KiB
Java
Raw Normal View History

2023-03-04 12:19:01 +00:00
package nu.marginalia.screenshot;
2022-05-19 15:45:26 +00:00
import com.google.common.base.Strings;
import com.google.inject.Inject;
import com.zaxxer.hikari.HikariDataSource;
import nu.marginalia.db.DbDomainQueries;
2022-07-26 15:10:11 +00:00
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
2022-05-19 15:45:26 +00:00
import spark.Request;
import spark.Response;
import java.io.IOException;
import java.sql.SQLException;
2022-05-19 15:45:26 +00:00
import static java.lang.Integer.parseInt;
public class ScreenshotService {
2023-03-04 12:19:01 +00:00
private final DbDomainQueries domainQueries;
private final HikariDataSource dataSource;
private final Logger logger = LoggerFactory.getLogger(getClass());
2022-05-19 15:45:26 +00:00
@Inject
2023-03-04 12:19:01 +00:00
public ScreenshotService(DbDomainQueries dbDomainQueries, HikariDataSource dataSource) {
this.domainQueries = dbDomainQueries;
this.dataSource = dataSource;
2022-05-19 15:45:26 +00:00
}
public boolean hasScreenshot(int domainId) {
try (var conn = dataSource.getConnection();
var ps = conn.prepareStatement("""
SELECT TRUE
FROM DATA_DOMAIN_SCREENSHOT
INNER JOIN EC_DOMAIN ON EC_DOMAIN.DOMAIN_NAME=DATA_DOMAIN_SCREENSHOT.DOMAIN_NAME
WHERE EC_DOMAIN.ID=?
""")) {
ps.setInt(1, domainId);
var rs = ps.executeQuery();
2022-07-26 15:10:11 +00:00
if (rs.next()) {
return rs.getBoolean(1);
}
2022-05-19 15:45:26 +00:00
}
catch (SQLException ex) {
logger.warn("SQL error", ex);
2022-05-19 15:45:26 +00:00
}
return false;
2022-05-19 15:45:26 +00:00
}
public Object serveScreenshotRequest(Request request, Response response) {
if (Strings.isNullOrEmpty(request.params("id"))) {
response.redirect("https://search.marginalia.nu/");
return null;
}
int id = parseInt(request.params("id"));
try (var conn = dataSource.getConnection();
var ps = conn.prepareStatement("""
SELECT CONTENT_TYPE, DATA
FROM DATA_DOMAIN_SCREENSHOT
INNER JOIN EC_DOMAIN ON EC_DOMAIN.DOMAIN_NAME=DATA_DOMAIN_SCREENSHOT.DOMAIN_NAME
WHERE EC_DOMAIN.ID=?
""")) {
ps.setInt(1, id);
var rsp = ps.executeQuery();
if (rsp.next()) {
response.type(rsp.getString(1));
2022-07-26 15:10:11 +00:00
response.status(200);
response.header("Cache-control", "public,max-age=3600");
IOUtils.copy(rsp.getBlob(2).getBinaryStream(), response.raw().getOutputStream());
return "";
2022-05-19 15:45:26 +00:00
}
}
catch (IOException ex) {
logger.warn("IO error", ex);
}
catch (SQLException ex) {
logger.warn("SQL error", ex);
2022-05-19 15:45:26 +00:00
}
return serveSvgPlaceholder(response, id);
2022-05-19 15:45:26 +00:00
}
private Object serveSvgPlaceholder(Response response, int id) {
var name = domainQueries.getDomain(id).map(Object::toString)
.orElse("[Screenshot Not Yet Captured]");
response.type("image/svg+xml");
return """
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns="http://www.w3.org/2000/svg"
width="640px"
height="480px"
viewBox="0 0 640 480"
version="1.1">
<g>
<rect
style="fill:#808080"
id="rect288"
width="595.41992"
height="430.01825"
x="23.034981"
y="27.850344" />
<text
xml:space="preserve"
style="font-size:100px;fill:#909090;font-family:sans-serif;"
x="20"
y="120">Placeholder</text>
<text
xml:space="preserve"
style="font-size:32px;fill:#000000;font-family:monospace;"
x="320" y="240" dominant-baseline="middle" text-anchor="middle">%s</text>
</g>
2023-04-17 16:04:22 +00:00
</svg>
""".formatted(name);
}
2022-05-19 15:45:26 +00:00
}