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;
|
2022-07-20 10:02:26 +00:00
|
|
|
import com.zaxxer.hikari.HikariDataSource;
|
2022-05-19 15:45:26 +00:00
|
|
|
import lombok.SneakyThrows;
|
2023-03-25 14:26:17 +00:00
|
|
|
import nu.marginalia.db.DbDomainQueries;
|
2022-07-26 15:10:11 +00:00
|
|
|
import org.apache.commons.io.IOUtils;
|
2022-07-20 10:02:26 +00:00
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
2022-05-19 15:45:26 +00:00
|
|
|
import spark.Request;
|
|
|
|
import spark.Response;
|
|
|
|
|
2022-07-20 10:02:26 +00:00
|
|
|
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;
|
2022-07-20 10:02:26 +00:00
|
|
|
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;
|
2022-07-20 10:02:26 +00:00
|
|
|
this.dataSource = dataSource;
|
2022-05-19 15:45:26 +00:00
|
|
|
}
|
|
|
|
|
2023-08-24 15:46:02 +00:00
|
|
|
public boolean hasScreenshot(int domainId) {
|
2022-07-20 10:02:26 +00:00
|
|
|
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=?
|
|
|
|
""")) {
|
2023-08-24 15:46:02 +00:00
|
|
|
ps.setInt(1, domainId);
|
2022-07-20 10:02:26 +00:00
|
|
|
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
|
|
|
}
|
2022-07-20 10:02:26 +00:00
|
|
|
catch (SQLException ex) {
|
|
|
|
logger.warn("SQL error", ex);
|
2022-05-19 15:45:26 +00:00
|
|
|
}
|
2022-07-20 10:02:26 +00:00
|
|
|
return false;
|
2022-05-19 15:45:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@SneakyThrows
|
|
|
|
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"));
|
|
|
|
|
2022-07-20 10:02:26 +00:00
|
|
|
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());
|
2022-07-20 10:02:26 +00:00
|
|
|
return "";
|
2022-05-19 15:45:26 +00:00
|
|
|
}
|
|
|
|
}
|
2022-07-20 10:02:26 +00:00
|
|
|
catch (SQLException ex) {
|
|
|
|
logger.warn("SQL error", ex);
|
2022-05-19 15:45:26 +00:00
|
|
|
}
|
|
|
|
|
2022-07-20 10:02:26 +00:00
|
|
|
return serveSvgPlaceholder(response, id);
|
2022-05-19 15:45:26 +00:00
|
|
|
}
|
|
|
|
|
2022-07-20 10:02:26 +00:00
|
|
|
private Object serveSvgPlaceholder(Response response, int id) {
|
2022-10-19 13:00:04 +00:00
|
|
|
|
2023-08-24 15:46:02 +00:00
|
|
|
var name = domainQueries.getDomain(id).map(Object::toString)
|
2023-03-08 17:36:41 +00:00
|
|
|
.orElse("[Screenshot Not Yet Captured]");
|
2022-10-19 13:00:04 +00:00
|
|
|
|
2022-07-20 10:02:26 +00:00
|
|
|
response.type("image/svg+xml");
|
2023-03-08 17:36:41 +00:00
|
|
|
|
|
|
|
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>
|
2023-03-08 17:36:41 +00:00
|
|
|
""".formatted(name);
|
2022-07-20 10:02:26 +00:00
|
|
|
}
|
2022-05-19 15:45:26 +00:00
|
|
|
}
|