This commit is contained in:
2024-01-29 12:51:59 -06:00
parent e85a09c40b
commit bf0b3814cb
17 changed files with 580 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
package tech.nevets.sheetrender;
import static spark.Spark.*;
public class Server {
public static void main(String[] args) {
port(8080);
get("/spreadsheetrender/:sheetId/schedule.png", new SheetRenderingRoute());
}
}

View File

@@ -0,0 +1,146 @@
package tech.nevets.sheetrender;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import spark.Request;
import spark.Response;
import spark.Route;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.HashMap;
import java.util.Map;
// Route: "/spreadsheetrender/:sheetId/schedule.png"
public class SheetRenderingRoute implements Route {
private static final String URL_F = "https://docs.google.com/spreadsheets/d/e/";
private static final String URL_B_CSV = "/pub?gid=0&single=true&output=csv";
private static final String URL_B_HTML = "/pubhtml?gid=0&single=true";
private static Font plainFont;
private static Font boldFont;
static {
try {
plainFont = Font.createFont(Font.TRUETYPE_FONT, SheetRenderingRoute.class.getResourceAsStream("/font.ttf")).deriveFont(Font.PLAIN, 24f);
boldFont = Font.createFont(Font.TRUETYPE_FONT, SheetRenderingRoute.class.getResourceAsStream("/font-bold.ttf")).deriveFont(Font.PLAIN, 26f);
} catch (FontFormatException | IOException e) {
e.printStackTrace();
}
}
@Override
public Object handle(Request req, Response res) throws Exception {
try {
String sheetRes = getRequest(URL_F + req.params(":sheetId") + URL_B_CSV);
String[][] csv = new String[11][8];
String[] rows = sheetRes.split("\n");
for (int i = 0; i < rows.length && i < 11; i++) {
String[] column = rows[i].split(",");
for (int j = 0; j < column.length && j < 8; j++) {
csv[i][j] = column[j];
}
}
BufferedImage img = renderImage(csv, getColorData(req.params(":sheetId")));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "png", baos);
res.type("image/png");
res.status(200);
return baos.toByteArray();
} catch (final Exception e) {
e.printStackTrace();
res.type("plain/text");
res.status(404);
return "Error!";
}
}
// Box Size: 178x37
private BufferedImage renderImage(String[][] data, Map<String, Color> colorMap) throws IOException {
BufferedImage img = new BufferedImage(1426, 409, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = img.createGraphics();
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
for (int r = 0; r < data.length; r++) {
for (int c = 0; c < data[c].length; c++) {
if (data[r][c] == null) {
g.setColor(Color.WHITE);
g.fillRect((178 * c), (37 * r), 178, 37);
continue;
}
Color color = colorMap.get(data[r][c]);
g.setColor(color == null ? Color.WHITE : color);
g.fillRect((178 * c), (37 * r), 178, 37);
g.setColor(Color.BLACK);
if (c == 0 || c == 3 || r == 0) {
g.setFont(boldFont);
} else {
g.setFont(plainFont);
}
g.drawString(data[r][c], (178 * c) + 10, (37 * r) + 27);
}
}
g.drawImage(ImageIO.read(this.getClass().getResource("/grid.png")), 0, 0, 1426, 409, null);
g.dispose();
return img;
}
private String getRequest(String url) {
try (HttpClient client = HttpClient.newHttpClient()) {
HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(URI.create(url))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.headers().firstValue("Location").isPresent()) {
return getRequest(response.headers().firstValue("Location").get());
}
return response.body();
} catch (final Exception e) {
e.printStackTrace();
return e.getMessage();
}
}
private Map<String, Color> getColorData(String sheetId) throws IOException {
Map<String, Color> colorMap = new HashMap<>();
Document doc = Jsoup.parse(getRequest(URL_F + sheetId + URL_B_HTML));
//Document doc = Jsoup.connect(URL_F + sheetId + URL_B_HTML).get();
Elements cells = doc.select("td[class^=s]");
for (Element cell : cells) {
String text = cell.text();
Color color = getColorFromCssClass(cell.className());
// Only add non-empty text and valid colors to the map
if (!text.isEmpty() && color != null) {
colorMap.put(text, color);
}
}
return colorMap;
}
private Color getColorFromCssClass(String className) {
return switch (className) {
case "s1" -> Color.GREEN;
case "s2" -> Color.YELLOW;
case "s4" -> Color.RED;
default -> Color.WHITE;
};
}
}

Binary file not shown.

BIN
src/main/resources/font.ttf Normal file

Binary file not shown.

BIN
src/main/resources/grid.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB