aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/com/pinapelz/Database.java604
-rw-r--r--src/main/java/com/pinapelz/FileSystem.java23
-rw-r--r--src/main/java/com/pinapelz/frontend/App.kt163
3 files changed, 403 insertions, 387 deletions
diff --git a/src/main/java/com/pinapelz/Database.java b/src/main/java/com/pinapelz/Database.java
index 0e8e984..7bec9ee 100644
--- a/src/main/java/com/pinapelz/Database.java
+++ b/src/main/java/com/pinapelz/Database.java
@@ -1,389 +1,413 @@
-/*
-Postgres will serve as the index for managing all the files. Iteration through all messages is too slow
- */
package com.pinapelz;
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+
+import javax.sql.DataSource;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.sql.*;
-import java.sql.Types;
-import java.util.Properties;
+import java.time.OffsetDateTime;
+import java.util.ArrayList;
+import java.util.List;
public class Database {
- private Connection conn;
+ private final DataSource ds;
+
+ public record FileEntry(
+ int fileId,
+ String fileName,
+ String description,
+ long size,
+ String mimeType,
+ OffsetDateTime createdAt
+ ) {}
+
+ public record DirectoryEntry(
+ int directoryId,
+ String path,
+ OffsetDateTime createdAt,
+ int fileCount
+ ) {}
- public Database(String host, String user, String password, String db){
+ public record FilePartialEntry(
+ long partialId,
+ String channelId,
+ String messageId,
+ String partName,
+ int partNumber,
+ long partSize,
+ String originalFilename,
+ String mimeType,
+ boolean uploadedViaWebhook,
+ OffsetDateTime createdAt
+ ) {}
+
+ public record PartialGroupEntry(
+ String originalFilename,
+ String mimeType,
+ int directoryId,
+ OffsetDateTime createdAt,
+ long size,
+ String description
+ ) {}
+
+ public Database(String host, String user, String password, String db) {
try {
- conn = createDBConnection(host, user, password, db);
- System.out.println("[Database] Running schema.sql as necessary");
- String schemaSQL = Files.readString(Path.of("schema.sql"));
- Statement statement = conn.createStatement();
- statement.execute(schemaSQL);
+ ds = createDataSource(host, user, password, db);
+ try (Connection c = ds.getConnection();
+ Statement s = c.createStatement()) {
+ s.execute(Files.readString(Path.of("schema.sql")));
+ }
} catch (IOException | SQLException e) {
throw new RuntimeException(e);
}
-
}
- public static Connection createDBConnection(String host, String user, String password, String db) throws IOException, SQLException {
- String url = "jdbc:postgresql://"+host+"/"+db+"?sslmode=require&channel_binding=require";
- Properties props = new Properties();
- props.setProperty("user", user);
- props.setProperty("password", password);
- return DriverManager.getConnection(url, props);
+ private static DataSource createDataSource(String host, String user, String pass, String db) {
+ HikariConfig c = new HikariConfig();
+ c.setJdbcUrl("jdbc:postgresql://" + host + "/" + db + "?sslmode=require&channel_binding=require");
+ c.setUsername(user);
+ c.setPassword(pass);
+ c.setMaximumPoolSize(3);
+ c.setMinimumIdle(1);
+ c.setIdleTimeout(60_000);
+ c.setMaxLifetime(600_000);
+ c.addDataSourceProperty("reWriteBatchedInserts", "true");
+ return new HikariDataSource(c);
}
- public void recordFileMetadata(String channelId, String messageId, int rootDirId, String fileName, String description, int size, String mimeType) throws SQLException {
- PreparedStatement ps = conn.prepareStatement("""
- INSERT INTO files (
- disc_channel_id,
- disc_message_id,
- directory_id,
- file_name,
- file_description,
- size,
- mime_type
- )
- VALUES (?, ?, ?, ?, ?, ?, ?)
-""");
- ps.setString(1, channelId);
- ps.setString(2, messageId);
- ps.setLong(3, rootDirId);
- ps.setString(4, fileName);
- ps.setString(5, description);
- ps.setLong(6, size);
- ps.setString(7, mimeType);
- ps.executeUpdate();
+ public void recordFileMetadata(
+ String channelId, String messageId, int dirId,
+ String name, String desc, int size, String mime
+ ) throws SQLException {
+
+ String sql = """
+ INSERT INTO files
+ (disc_channel_id, disc_message_id, directory_id,
+ file_name, file_description, size, mime_type)
+ VALUES (?, ?, ?, ?, ?, ?, ?)
+ """;
+
+ try (Connection c = ds.getConnection();
+ PreparedStatement p = c.prepareStatement(sql)) {
+ p.setString(1, channelId);
+ p.setString(2, messageId);
+ p.setInt(3, dirId);
+ p.setString(4, name);
+ p.setString(5, desc);
+ p.setInt(6, size);
+ p.setString(7, mime);
+ p.executeUpdate();
+ }
}
public String[] getFileById(int fileId) {
String sql = """
- SELECT
- disc_channel_id,
- disc_message_id,
- file_name
- FROM files
- WHERE file_id = ?
- """;
-
- try (PreparedStatement ps = conn.prepareStatement(sql)) {
- ps.setInt(1, fileId);
-
- try (ResultSet rs = ps.executeQuery()) {
- if (!rs.next()) {
- throw new RuntimeException("File not found for id=" + fileId);
- }
+ SELECT disc_channel_id, disc_message_id, file_name
+ FROM files WHERE file_id = ?
+ """;
- String channelId = rs.getString("disc_channel_id");
- String messageId = rs.getString("disc_message_id");
- String fileName = rs.getString("file_name");
+ try (Connection c = ds.getConnection();
+ PreparedStatement p = c.prepareStatement(sql)) {
- return new String[]{ channelId, messageId, fileName };
+ p.setInt(1, fileId);
+ try (ResultSet r = p.executeQuery()) {
+ if (!r.next()) throw new RuntimeException();
+ return new String[]{ r.getString(1), r.getString(2), r.getString(3) };
}
-
} catch (SQLException e) {
- throw new RuntimeException("Failed to fetch file metadata", e);
+ throw new RuntimeException(e);
}
}
- public ResultSet getFilesByDirectoryId(int directoryId, String search, String mimeTypeFilter, String sortBy) {
- StringBuilder sql = new StringBuilder("""
- SELECT
- file_id,
- file_name,
- file_description,
- size,
- mime_type,
- created_at
- FROM files
- WHERE directory_id = ?
- """);
+ public List<FileEntry> getFilesByDirectoryId(
+ int dirId, String search, String mime, String sort
+ ) {
- if (search != null && !search.trim().isEmpty()) {
- sql.append(" AND (LOWER(file_name) LIKE ? OR LOWER(file_description) LIKE ?)");
- }
+ StringBuilder q = new StringBuilder("""
+ SELECT file_id, file_name, file_description,
+ size, mime_type, created_at
+ FROM files WHERE directory_id = ?
+ """);
- if (mimeTypeFilter != null && !mimeTypeFilter.trim().isEmpty()) {
- sql.append(" AND mime_type LIKE ?");
- }
+ if (search != null && !search.isBlank())
+ q.append(" AND (LOWER(file_name) LIKE ? OR LOWER(file_description) LIKE ?)");
+ if (mime != null && !mime.isBlank())
+ q.append(" AND mime_type LIKE ?");
- switch (sortBy) {
- case "file_name":
- sql.append(" ORDER BY file_name ASC");
- break;
- case "size":
- sql.append(" ORDER BY size DESC");
- break;
- default:
- sql.append(" ORDER BY created_at DESC");
- break;
- }
+ q.append(" ORDER BY ")
+ .append("size".equals(sort) ? "size DESC" :
+ "file_name".equals(sort) ? "file_name ASC" :
+ "created_at DESC");
- try {
- PreparedStatement ps = conn.prepareStatement(sql.toString());
- int paramIndex = 1;
+ try (Connection c = ds.getConnection();
+ PreparedStatement p = c.prepareStatement(q.toString())) {
- ps.setInt(paramIndex++, directoryId);
+ int i = 1;
+ p.setInt(i++, dirId);
- if (search != null && !search.trim().isEmpty()) {
- String searchPattern = "%" + search.toLowerCase() + "%";
- ps.setString(paramIndex++, searchPattern);
- ps.setString(paramIndex++, searchPattern);
+ if (search != null && !search.isBlank()) {
+ String s = "%" + search.toLowerCase() + "%";
+ p.setString(i++, s);
+ p.setString(i++, s);
}
- if (mimeTypeFilter != null && !mimeTypeFilter.trim().isEmpty()) {
- ps.setString(paramIndex++, mimeTypeFilter + "%");
+ if (mime != null && !mime.isBlank())
+ p.setString(i++, mime + "%");
+
+ List<FileEntry> out = new ArrayList<>();
+ try (ResultSet r = p.executeQuery()) {
+ while (r.next())
+ out.add(new FileEntry(
+ r.getInt(1), r.getString(2), r.getString(3),
+ r.getLong(4), r.getString(5),
+ r.getObject(6, OffsetDateTime.class)
+ ));
}
+ return out;
- return ps.executeQuery();
} catch (SQLException e) {
- throw new RuntimeException("Failed to fetch filtered files for directory", e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ public boolean deleteFile(int fileId) throws SQLException {
+ try (Connection c = ds.getConnection();
+ PreparedStatement p = c.prepareStatement("DELETE FROM files WHERE file_id = ?")) {
+ p.setInt(1, fileId);
+ return p.executeUpdate() > 0;
}
}
- public ResultSet getAllDirectories() {
+ public List<DirectoryEntry> getAllDirectories() {
String sql = """
- SELECT
- directory_id,
- path,
- created_at,
- (SELECT COUNT(*) FROM files WHERE directory_id = directories.directory_id) as file_count
- FROM directories
- ORDER BY path ASC
+ SELECT d.directory_id, d.path, d.created_at,
+ COUNT(f.file_id)
+ FROM directories d
+ LEFT JOIN files f USING (directory_id)
+ GROUP BY d.directory_id
+ ORDER BY d.path
""";
- try {
- PreparedStatement ps = conn.prepareStatement(sql);
- return ps.executeQuery();
+ try (Connection c = ds.getConnection();
+ PreparedStatement p = c.prepareStatement(sql);
+ ResultSet r = p.executeQuery()) {
+
+ List<DirectoryEntry> out = new ArrayList<>();
+ while (r.next())
+ out.add(new DirectoryEntry(
+ r.getInt(1), r.getString(2),
+ r.getObject(3, OffsetDateTime.class),
+ r.getInt(4)
+ ));
+ return out;
+
} catch (SQLException e) {
- throw new RuntimeException("Failed to fetch directories", e);
+ throw new RuntimeException(e);
}
}
- public ResultSet getDirectoryById(int directoryId) {
+ public DirectoryEntry getDirectoryById(int id) {
String sql = """
- SELECT
- directory_id,
- path,
- created_at,
- (SELECT COUNT(*) FROM files WHERE directory_id = directories.directory_id) as file_count
- FROM directories
- WHERE directory_id = ?
+ SELECT d.directory_id, d.path, d.created_at,
+ COUNT(f.file_id)
+ FROM directories d
+ LEFT JOIN files f USING (directory_id)
+ WHERE d.directory_id = ?
+ GROUP BY d.directory_id
""";
- try {
- PreparedStatement ps = conn.prepareStatement(sql);
- ps.setInt(1, directoryId);
- return ps.executeQuery();
+ try (Connection c = ds.getConnection();
+ PreparedStatement p = c.prepareStatement(sql)) {
+
+ p.setInt(1, id);
+ try (ResultSet r = p.executeQuery()) {
+ if (!r.next()) throw new RuntimeException();
+ return new DirectoryEntry(
+ r.getInt(1), r.getString(2),
+ r.getObject(3, OffsetDateTime.class),
+ r.getInt(4)
+ );
+ }
+
} catch (SQLException e) {
- throw new RuntimeException("Failed to fetch directory", e);
+ throw new RuntimeException(e);
}
}
public int createDirectory(String path) throws SQLException {
- String sql = """
- INSERT INTO directories (path)
- VALUES (?)
- ON CONFLICT (path) DO UPDATE SET path = EXCLUDED.path
- RETURNING directory_id
- """;
+ try (Connection c = ds.getConnection();
+ PreparedStatement p = c.prepareStatement("""
+ INSERT INTO directories (path)
+ VALUES (?)
+ ON CONFLICT (path) DO UPDATE SET path = EXCLUDED.path
+ RETURNING directory_id
+ """)) {
- try (PreparedStatement ps = conn.prepareStatement(sql)) {
- ps.setString(1, path);
- try (ResultSet rs = ps.executeQuery()) {
- if (rs.next()) {
- return rs.getInt("directory_id");
- }
- throw new SQLException("Failed to get directory ID");
+ p.setString(1, path);
+ try (ResultSet r = p.executeQuery()) {
+ r.next();
+ return r.getInt(1);
}
}
}
- public boolean deleteFile(int fileId) throws SQLException {
- String sql = """
- DELETE FROM files
- WHERE file_id = ?
- """;
+ public boolean deleteDirectory(int directoryId) throws SQLException {
+ if (directoryId == 1) throw new SQLException();
- try (PreparedStatement ps = conn.prepareStatement(sql)) {
- ps.setInt(1, fileId);
- int rowsAffected = ps.executeUpdate();
- return rowsAffected > 0;
+ try (Connection c = ds.getConnection()) {
+ try (PreparedStatement check = c.prepareStatement(
+ "SELECT COUNT(*) FROM files WHERE directory_id = ?")) {
+ check.setInt(1, directoryId);
+ try (ResultSet r = check.executeQuery()) {
+ r.next();
+ if (r.getInt(1) > 0) throw new SQLException();
+ }
+ }
+
+ try (PreparedStatement del = c.prepareStatement(
+ "DELETE FROM directories WHERE directory_id = ?")) {
+ del.setInt(1, directoryId);
+ return del.executeUpdate() > 0;
+ }
}
}
- public ResultSet getUniqueOriginalFilesFromPartials(int directoryId, String search) {
- StringBuilder sql = new StringBuilder("""
- SELECT DISTINCT
- original_filename,
- mime_type,
- directory_id,
- MAX(created_at) as created_at,
- SUM(part_size) as size,
- MAX(file_description) as file_description
- FROM file_partials
- WHERE directory_id = ?
- """);
+ public long recordFilePartial(
+ String channelId, String messageId, int dirId,
+ String partName, int partNumber, long partSize,
+ String original, String desc, String mime
+ ) throws SQLException {
- if (search != null && !search.trim().isEmpty()) {
- sql.append(" AND LOWER(original_filename) LIKE ?");
- }
+ String sql = """
+ INSERT INTO file_partials
+ (disc_channel_id, disc_message_id, directory_id,
+ part_name, part_number, part_size,
+ original_filename, file_description, mime_type,
+ uploaded_via_webhook)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, true)
+ RETURNING partial_id
+ """;
- sql.append("""
- GROUP BY original_filename, mime_type, directory_id
- ORDER BY original_filename ASC
- """);
+ try (Connection c = ds.getConnection();
+ PreparedStatement p = c.prepareStatement(sql)) {
- try {
- PreparedStatement ps = conn.prepareStatement(sql.toString());
- int paramIndex = 1;
- ps.setInt(paramIndex++, directoryId);
+ p.setString(1, channelId);
+ p.setString(2, messageId);
+ p.setInt(3, dirId);
+ p.setString(4, partName);
+ p.setInt(5, partNumber);
+ p.setLong(6, partSize);
+ p.setString(7, original);
+ p.setString(8, desc);
+ p.setString(9, mime);
- if (search != null && !search.trim().isEmpty()) {
- ps.setString(paramIndex++, "%" + search.toLowerCase() + "%");
+ try (ResultSet r = p.executeQuery()) {
+ r.next();
+ return r.getLong(1);
}
-
- return ps.executeQuery();
- } catch (SQLException e) {
- throw new RuntimeException("Failed to fetch unique original files from partials", e);
}
}
- public boolean deleteDirectory(int directoryId) throws SQLException {
- String checkSql = """
- SELECT COUNT(*) as file_count
- FROM files
- WHERE directory_id = ?
- """;
-
- try (PreparedStatement checkPs = conn.prepareStatement(checkSql)) {
- checkPs.setInt(1, directoryId);
- try (ResultSet rs = checkPs.executeQuery()) {
- if (rs.next() && rs.getInt("file_count") > 0) {
- throw new SQLException("Cannot delete directory: contains files");
- }
+ public boolean checkPartialExists(String partName, int dirId) throws SQLException {
+ try (Connection c = ds.getConnection();
+ PreparedStatement p = c.prepareStatement(
+ "SELECT COUNT(*) FROM file_partials WHERE part_name = ? AND directory_id = ?")) {
+ p.setString(1, partName);
+ p.setInt(2, dirId);
+ try (ResultSet r = p.executeQuery()) {
+ r.next();
+ return r.getInt(1) > 0;
}
}
+ }
- if (directoryId == 1) {
- throw new SQLException("Cannot delete root directory");
- }
-
- String deleteSql = """
- DELETE FROM directories
- WHERE directory_id = ?
- """;
-
- try (PreparedStatement deletePs = conn.prepareStatement(deleteSql)) {
- deletePs.setInt(1, directoryId);
- int rowsAffected = deletePs.executeUpdate();
- return rowsAffected > 0;
+ public boolean deleteFilePartials(String original, int dirId) throws SQLException {
+ try (Connection c = ds.getConnection();
+ PreparedStatement p = c.prepareStatement(
+ "DELETE FROM file_partials WHERE original_filename = ? AND directory_id = ?")) {
+ p.setString(1, original);
+ p.setInt(2, dirId);
+ return p.executeUpdate() > 0;
}
}
- public long recordFilePartial(String channelId, String messageId, int directoryId,
- String partName, int partNumber, long partSize,
- String originalFilename, String description, String mimeType) throws SQLException {
+ public List<FilePartialEntry> getFilePartialsByOriginalFilename(String original, int dirId) {
String sql = """
- INSERT INTO file_partials (
- disc_channel_id,
- disc_message_id,
- directory_id,
- part_name,
- part_number,
- part_size,
- original_filename,
- file_description,
- mime_type,
- uploaded_via_webhook
- )
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- RETURNING partial_id
+ SELECT partial_id, disc_channel_id, disc_message_id,
+ part_name, part_number, part_size,
+ original_filename, mime_type,
+ uploaded_via_webhook, created_at
+ FROM file_partials
+ WHERE original_filename = ? AND directory_id = ?
+ ORDER BY part_number
""";
- try (PreparedStatement ps = conn.prepareStatement(sql)) {
- ps.setString(1, channelId);
- ps.setString(2, messageId);
- ps.setInt(3, directoryId);
- ps.setString(4, partName);
- ps.setInt(5, partNumber);
- ps.setLong(6, partSize);
- ps.setString(7, originalFilename);
- ps.setString(8, description);
- ps.setString(9, mimeType);
- ps.setBoolean(10, true);
+ try (Connection c = ds.getConnection();
+ PreparedStatement p = c.prepareStatement(sql)) {
- try (ResultSet rs = ps.executeQuery()) {
- if (rs.next()) {
- return rs.getLong("partial_id");
- }
- throw new SQLException("Failed to get partial ID");
+ p.setString(1, original);
+ p.setInt(2, dirId);
+
+ List<FilePartialEntry> out = new ArrayList<>();
+ try (ResultSet r = p.executeQuery()) {
+ while (r.next())
+ out.add(new FilePartialEntry(
+ r.getLong(1), r.getString(2), r.getString(3),
+ r.getString(4), r.getInt(5), r.getLong(6),
+ r.getString(7), r.getString(8),
+ r.getBoolean(9),
+ r.getObject(10, OffsetDateTime.class)
+ ));
}
+ return out;
+
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
}
}
- public boolean checkPartialExists(String partName, int directoryId) throws SQLException {
- String sql = """
- SELECT COUNT(*) as count
- FROM file_partials
- WHERE part_name = ? AND directory_id = ?
- """;
+ public List<PartialGroupEntry> getUniqueOriginalFilesFromPartials(int dirId, String search) {
+ StringBuilder q = new StringBuilder("""
+ SELECT original_filename, mime_type, directory_id,
+ MAX(created_at), SUM(part_size), MAX(file_description)
+ FROM file_partials
+ WHERE directory_id = ?
+ """);
- try (PreparedStatement ps = conn.prepareStatement(sql)) {
- ps.setString(1, partName);
- ps.setInt(2, directoryId);
- try (ResultSet rs = ps.executeQuery()) {
- if (rs.next()) {
- return rs.getInt("count") > 0;
- }
- return false;
- }
- }
- }
+ if (search != null && !search.isBlank())
+ q.append(" AND LOWER(original_filename) LIKE ?");
- public boolean deleteFilePartials(String originalFilename, int directoryId) throws SQLException {
- String sql = """
- DELETE FROM file_partials
- WHERE original_filename = ? AND directory_id = ?
- """;
+ q.append(" GROUP BY original_filename, mime_type, directory_id ORDER BY original_filename");
- try (PreparedStatement ps = conn.prepareStatement(sql)) {
- ps.setString(1, originalFilename);
- ps.setInt(2, directoryId);
- int rowsAffected = ps.executeUpdate();
- return rowsAffected > 0;
- }
- }
+ try (Connection c = ds.getConnection();
+ PreparedStatement p = c.prepareStatement(q.toString())) {
- public ResultSet getFilePartialsByOriginalFilename(String originalFilename, int directoryId) {
- String sql = """
- SELECT
- partial_id,
- disc_channel_id,
- disc_message_id,
- part_name,
- part_number,
- part_size,
- original_filename,
- mime_type,
- uploaded_via_webhook,
- created_at
- FROM file_partials
- WHERE original_filename = ? AND directory_id = ?
- ORDER BY part_number ASC
- """;
+ int i = 1;
+ p.setInt(i++, dirId);
+ if (search != null && !search.isBlank())
+ p.setString(i++, "%" + search.toLowerCase() + "%");
+
+ List<PartialGroupEntry> out = new ArrayList<>();
+ try (ResultSet r = p.executeQuery()) {
+ while (r.next())
+ out.add(new PartialGroupEntry(
+ r.getString(1),
+ r.getString(2),
+ r.getInt(3),
+ r.getObject(4, OffsetDateTime.class),
+ r.getLong(5),
+ r.getString(6)
+ ));
+ }
+ return out;
- try {
- PreparedStatement ps = conn.prepareStatement(sql);
- ps.setString(1, originalFilename);
- ps.setInt(2, directoryId);
- return ps.executeQuery();
} catch (SQLException e) {
- throw new RuntimeException("Failed to fetch file partials", e);
+ throw new RuntimeException(e);
}
}
-
}
diff --git a/src/main/java/com/pinapelz/FileSystem.java b/src/main/java/com/pinapelz/FileSystem.java
index e86cf6e..6f72efd 100644
--- a/src/main/java/com/pinapelz/FileSystem.java
+++ b/src/main/java/com/pinapelz/FileSystem.java
@@ -4,6 +4,7 @@ import net.dv8tion.jda.api.entities.Message;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.List;
public class FileSystem {
@@ -32,29 +33,25 @@ public class FileSystem {
}
}
- public ResultSet getFilesByDirectoryId(int directoryId, String search, String mimeTypeFilter, String sortBy) {
+ public List<Database.FileEntry> getFilesByDirectoryId(int directoryId, String search, String mimeTypeFilter, String sortBy) {
return database.getFilesByDirectoryId(directoryId, search, mimeTypeFilter, sortBy);
}
public int findOrCreateDirectory(String path) throws SQLException {
- ResultSet rs = getAllDirectories();
- while (rs.next()) {
- if (path.equals(rs.getString("path"))) {
- int id = rs.getInt("directory_id");
- rs.close();
- return id;
+ for (Database.DirectoryEntry d : getAllDirectories()) {
+ if (path.equals(d.path())) {
+ return d.directoryId();
}
}
- rs.close();
-
return createDirectory(path);
}
- public ResultSet getAllDirectories() {
+
+ public List<Database.DirectoryEntry> getAllDirectories() {
return database.getAllDirectories();
}
- public ResultSet getDirectoryById(int directoryId) {
+ public Database.DirectoryEntry getDirectoryById(int directoryId) {
return database.getDirectoryById(directoryId);
}
@@ -77,11 +74,11 @@ public class FileSystem {
partNumber, partSize, originalFilename, description, mimeType);
}
- public ResultSet getFilePartialsByOriginalFilename(String originalFilename, int directoryId) {
+ public List<Database.FilePartialEntry> getFilePartialsByOriginalFilename(String originalFilename, int directoryId) {
return database.getFilePartialsByOriginalFilename(originalFilename, directoryId);
}
- public ResultSet getGroupedPartials(int directoryId, String search) {
+ public List<Database.PartialGroupEntry> getGroupedPartials(int directoryId, String search) {
return database.getUniqueOriginalFilesFromPartials(directoryId, search);
}
diff --git a/src/main/java/com/pinapelz/frontend/App.kt b/src/main/java/com/pinapelz/frontend/App.kt
index fd5d75c..a5961d4 100644
--- a/src/main/java/com/pinapelz/frontend/App.kt
+++ b/src/main/java/com/pinapelz/frontend/App.kt
@@ -3,10 +3,11 @@ package com.pinapelz.frontend
import io.javalin.Javalin
import com.pinapelz.Retriever
import com.pinapelz.FileSystem
-import java.sql.ResultSet
import java.text.SimpleDateFormat
import java.io.File
import java.net.URLEncoder
+import java.time.ZoneId
+import java.time.format.DateTimeFormatter
fun startFrontend(retriever: Retriever, fileSystem: FileSystem, webhooksFile: String) {
// Initialize WebhookManager if webhooks file exists
@@ -32,29 +33,6 @@ fun startFrontend(retriever: Retriever, fileSystem: FileSystem, webhooksFile: St
ctx.html(generateFileSplitterHtml())
}
- /*
- {
- "success": true,
- "parts": [
- {
- "id": "unique-part-id-1",
- "name": "filename.part001.nitro",
- "size": 26214400
- },
- {
- "id": "unique-part-id-2",
- "name": "filename.part002.nitro",
- "size": 26214400
- },
- {
- "id": "unique-part-id-3",
- "name": "filename.part003.nitro",
- "size": 15728640
- }
- ]
-}
-
- */
app.post("/api/split") { ctx ->
val manager = MultipartFileManager(fileSystem, webhookManager)
val result = manager.handleSplitRequest(ctx)
@@ -64,37 +42,37 @@ fun startFrontend(retriever: Retriever, fileSystem: FileSystem, webhooksFile: St
app.get("/api/directories") { ctx ->
val directories = mutableListOf<Map<String, Any>>()
val rs = fileSystem.getAllDirectories()
-
- while (rs.next()) {
- directories.add(mapOf(
- "id" to rs.getInt("directory_id"),
- "path" to rs.getString("path"),
- "fileCount" to rs.getInt("file_count"),
- "created" to rs.getTimestamp("created_at").toString()
- ))
+ for (d in rs) {
+ directories.add(
+ mapOf(
+ "id" to d.directoryId,
+ "path" to d.path,
+ "fileCount" to d.fileCount,
+ "created" to d.createdAt.toString()
+ )
+ )
}
- rs.close()
+
ctx.json(directories)
}
app.get("/api/directory/{id}") { ctx ->
val directoryId = ctx.pathParam("id").toInt()
- val rs = fileSystem.getDirectoryById(directoryId)
+ val d = fileSystem.getDirectoryById(directoryId)
- if (rs.next()) {
+ if (d != null) {
val directory = mapOf(
- "id" to rs.getInt("directory_id"),
- "path" to rs.getString("path"),
- "fileCount" to rs.getInt("file_count"),
- "created" to rs.getTimestamp("created_at").toString()
+ "id" to d.directoryId,
+ "path" to d.path,
+ "fileCount" to d.fileCount,
+ "created" to d.createdAt.toString()
)
- rs.close()
ctx.json(directory)
} else {
- rs.close()
ctx.status(404).result("Directory not found")
}
+
}
app.get("/api/files") { ctx ->
@@ -104,55 +82,71 @@ fun startFrontend(retriever: Retriever, fileSystem: FileSystem, webhooksFile: St
val sortBy = ctx.queryParam("sortBy") ?: "created_at"
val files = mutableListOf<Map<String, Any>>()
- val rs: ResultSet = fileSystem.getFilesByDirectoryId(directoryId, search, mimeTypeFilter, sortBy)
val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
- while (rs.next()) {
- files.add(mapOf(
- "id" to rs.getInt("file_id"),
- "name" to rs.getString("file_name"),
- "description" to (rs.getString("file_description") ?: ""),
- "size" to formatFileSize(rs.getLong("size")),
- "mimeType" to (rs.getString("mime_type") ?: "unknown"),
- "created" to dateFormat.format(rs.getTimestamp("created_at"))
- ))
+// regular files
+ val fileEntries = fileSystem.getFilesByDirectoryId(
+ directoryId,
+ search,
+ mimeTypeFilter,
+ sortBy
+ )
+
+ for (f in fileEntries) {
+ files.add(
+ mapOf(
+ "id" to f.fileId,
+ "name" to f.fileName,
+ "description" to (f.description ?: ""),
+ "size" to formatFileSize(f.size),
+ "mimeType" to (f.mimeType ?: "unknown"),
+ "created" to DateTimeFormatter
+ .ofPattern("yyyy-MM-dd HH:mm:ss")
+ .withZone(ZoneId.systemDefault())
+ .format(f.createdAt)
+ )
+ )
}
- rs.close()
- val partialsRs = fileSystem.getGroupedPartials(directoryId, search)
- while (partialsRs.next()) {
- val originalName = partialsRs.getString("original_filename")
- val partialDescription = partialsRs.getString("file_description")
- files.add(mapOf(
- "id" to "partial:$originalName|$directoryId",
- "name" to originalName,
- "description" to (partialDescription ?: ""),
- "size" to formatFileSize(partialsRs.getLong("size")),
- "mimeType" to (partialsRs.getString("mime_type") ?: "application/octet-stream"),
- "created" to dateFormat.format(partialsRs.getTimestamp("created_at"))
- ))
+
+ val partials = fileSystem.getGroupedPartials(directoryId, search)
+ for (p in partials) {
+ files.add(
+ mapOf(
+ "id" to "partial:${p.originalFilename}|$directoryId",
+ "name" to p.originalFilename,
+ "description" to (p.description ?: ""),
+ "size" to formatFileSize(p.size),
+ "mimeType" to (p.mimeType ?: "application/octet-stream"),
+ "created" to DateTimeFormatter
+ .ofPattern("yyyy-MM-dd HH:mm:ss")
+ .withZone(ZoneId.systemDefault())
+ .format(p.createdAt)
+ )
+ )
}
- partialsRs.close()
val html = generateFileTableHtml(files, search, mimeTypeFilter)
ctx.html(html)
ctx.header("HX-Trigger", "updateFileCount")
ctx.header("X-File-Count", files.size.toString())
+
}
app.get("/api/directories-html") { ctx ->
val directories = mutableListOf<Map<String, Any>>()
- val rs = fileSystem.getAllDirectories()
+ val directoriesResult = fileSystem.getAllDirectories()
- while (rs.next()) {
- directories.add(mapOf(
- "id" to rs.getInt("directory_id"),
- "path" to rs.getString("path"),
- "fileCount" to rs.getInt("file_count"),
- "created" to rs.getTimestamp("created_at").toString()
- ))
+ for (d in directoriesResult) {
+ directories.add(
+ mapOf(
+ "id" to d.directoryId,
+ "path" to d.path,
+ "fileCount" to d.fileCount,
+ "created" to d.createdAt.toString()
+ )
+ )
}
- rs.close()
val html = generateDirectoryListHtml(directories)
ctx.html(html)
@@ -269,21 +263,22 @@ fun startFrontend(retriever: Retriever, fileSystem: FileSystem, webhooksFile: St
val filename = ctx.queryParam("filename") ?: throw io.javalin.http.BadRequestResponse("filename required")
val dirId = ctx.queryParam("dir")?.toIntOrNull() ?: throw io.javalin.http.BadRequestResponse("dir id required")
- val rs = fileSystem.getFilePartialsByOriginalFilename(filename, dirId)
data class PartInfo(val channelId: String, val messageId: String, val partName: String, val isWebhook: Boolean)
val parts = mutableListOf<PartInfo>()
var mimeType = "application/octet-stream"
- while (rs.next()) {
- parts.add(PartInfo(
- rs.getString("disc_channel_id"),
- rs.getString("disc_message_id"),
- rs.getString("part_name"),
- rs.getBoolean("uploaded_via_webhook")
- ))
- mimeType = rs.getString("mime_type") ?: mimeType
+ for (p in fileSystem.getFilePartialsByOriginalFilename(filename, dirId)) {
+ parts.add(
+ PartInfo(
+ p.channelId,
+ p.messageId,
+ p.partName,
+ p.uploadedViaWebhook
+ )
+ )
+ mimeType = p.mimeType ?: mimeType
}
- rs.close()
+
if (parts.isEmpty()) {
ctx.status(404).result("No parts found for $filename")
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage