From b89ff9254cfdb8b624365a1f1442f74253ba223b Mon Sep 17 00:00:00 2001 From: Svjatoslav Agejenko Date: Sun, 22 Jun 2025 22:45:00 +0300 Subject: [PATCH] Add "DONE:" prefix to completed file names. Recursively scan all directories. --- .../MailCorrespondentCommand.java | 120 ++++++++---------- 1 file changed, 55 insertions(+), 65 deletions(-) diff --git a/src/main/java/eu/svjatoslav/alyverkko_cli/commands/mail_correspondant/MailCorrespondentCommand.java b/src/main/java/eu/svjatoslav/alyverkko_cli/commands/mail_correspondant/MailCorrespondentCommand.java index e336743..422d2d5 100644 --- a/src/main/java/eu/svjatoslav/alyverkko_cli/commands/mail_correspondant/MailCorrespondentCommand.java +++ b/src/main/java/eu/svjatoslav/alyverkko_cli/commands/mail_correspondant/MailCorrespondentCommand.java @@ -17,8 +17,7 @@ import java.util.*; import static eu.svjatoslav.alyverkko_cli.Main.configuration; import static eu.svjatoslav.commons.file.IOHelper.getFileContentsAsString; import static eu.svjatoslav.commons.file.IOHelper.saveToFile; -import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; -import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; +import static java.nio.file.StandardWatchEventKinds.*; /** @@ -147,21 +146,16 @@ public class MailCorrespondentCommand implements Command { directoryWatcher.close(); } - /** - * Performs an initial scan of existing files in the mail directory, - * adding those that need processing to the task queue. - * - * @throws IOException if file scanning fails. - */ private void initialMailScanAndReply() throws IOException { - File[] files = mailDir.listFiles(); - if (files == null) { - return; - } - - for (File file : files) { - considerFileForQueuing(file.toPath()); - } + Files.walk(mailDir.toPath()) + .filter(path -> Files.isRegularFile(path)) + .forEach(path -> { + try { + considerFileForQueuing(path); + } catch (IOException e) { + e.printStackTrace(); + } + }); } /** @@ -212,37 +206,10 @@ public class MailCorrespondentCommand implements Command { } } - /** - * Processes a file if it has the "TOCOMPUTE:" marker, running an AI - * query and appending the result to the file. Otherwise logs that - * it's being ignored. - * - * @param file the file to possibly process. - * @throws IOException if reading/writing the file fails. - * @throws InterruptedException if the AI query is interrupted. - */ - private void processMailIfNeeded(File file) throws IOException, InterruptedException { - if (!isMailProcessingNeeded(file)) { - System.out.println("Ignoring file: " + file.getName() + " (does not need processing for now)"); - return; - } - - System.out.println("\nReplying to mail: " + file.getName()); - - MailQuery mailQuery = buildMailQueryFromFile(file); - - // Run the query using the AI model while measuring the time taken - AiTask aiTask = new AiTask(mailQuery); - String aiGeneratedResponse = aiTask.runAiQuery(); - - saveAiResponseToFile(file, mailQuery, aiGeneratedResponse); - } - private static void saveAiResponseToFile(File file, MailQuery mailQuery, String aiResponse) throws IOException { - // Build new content StringBuilder resultFileContent = new StringBuilder(); - // The First line should be "TOCOMPUTE:" with settings that were used to process this file + // The First line should be "DONE:" with settings used to process this file resultFileContent.append(getDoneLine(mailQuery)); // Ensure the user prompt block is labeled if it isn't already @@ -259,10 +226,13 @@ public class MailCorrespondentCommand implements Command { .append(aiResponse) .append("\n"); - // Write the combined result back to the same file - saveToFile(file, resultFileContent.toString()); - } + File newFile = new File(file.getParentFile(), "DONE: " + file.getName()); + saveToFile(newFile, resultFileContent.toString()); + if (!file.delete()) { + System.err.println("Failed to delete original file: " + file.getAbsolutePath()); + } + } /** * Processes a task by reading the file, building the MailQuery, @@ -409,35 +379,55 @@ public class MailCorrespondentCommand implements Command { * @throws IOException if file processing fails. */ private void processDetectedFilesystemEvents(WatchKey key) throws IOException { + + Path dir = (Path) key.watchable(); // ★ new line + for (WatchEvent event : key.pollEvents()) { + WatchEvent.Kind kind = event.kind(); + if (kind != ENTRY_CREATE && kind != ENTRY_MODIFY) continue; - // Skip OVERFLOW events - if (kind == StandardWatchEventKinds.OVERFLOW) { - continue; - } + @SuppressWarnings("unchecked") + WatchEvent ev = (WatchEvent) event; + Path filename = ev.context(); - // The filename for the event - Path filename = ((WatchEvent) event).context(); - System.out.println("Event: " + kind + " for file: " + filename); + Path fullPath = dir.resolve(filename); + System.out.printf("Event: %s – %s%n", kind.name(), fullPath); - // Add to task queue if needed - if (kind == ENTRY_CREATE || kind == ENTRY_MODIFY) { - Path filePath = mailDir.toPath().resolve(filename); - considerFileForQueuing(filePath); + // If the entry is a *new directory* we need to start watching it, too: + if (kind == ENTRY_CREATE && Files.isDirectory(fullPath)) { + registerAllSubdirectories(fullPath); + } + + // And finally queue the file if it’s a regular, non-hidden file: + if (Files.isRegularFile(fullPath) && !Files.isHidden(fullPath)) { + considerFileForQueuing(fullPath); } } } - /** - * Registers the mail directory with a WatchService for ENTRY_CREATE - * and ENTRY_MODIFY events. - * - * @throws IOException if registration fails. - */ + private void initializeFileWatcher() throws IOException { this.directoryWatcher = FileSystems.getDefault().newWatchService(); - Paths.get(mailDir.getAbsolutePath()).register(directoryWatcher, ENTRY_CREATE, ENTRY_MODIFY); + registerAllSubdirectories(mailDir.toPath()); + } + + private void registerAllSubdirectories(Path path) { + try { + System.out.println("Registering directory for watch service: " + path); + path.register(directoryWatcher, ENTRY_CREATE, ENTRY_MODIFY); + if (Files.isDirectory(path)) { + try (DirectoryStream stream = Files.newDirectoryStream(path)) { + for (Path entry : stream) { + if (Files.isDirectory(entry)) { + registerAllSubdirectories(entry); + } + } + } + } + } catch (IOException e) { + System.err.println("Failed to register directory: " + path + " - " + e.getMessage()); + } } /** -- 2.20.1