package name.nathanmcrae.numbersstation; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.SftpException; import com.leakyabstractions.result.api.Result; import com.leakyabstractions.result.core.Results; import com.tearsofaunicorn.wordpress.api.model.Post; import com.tearsofaunicorn.wordpress.api.WordpressClient; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.Date; import java.util.logging.FileHandler; import java.util.logging.Logger; import java.util.logging.Level; import javafx.application.Application; import javafx.application.Platform; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; import org.apache.commons.cli.*; public class Main extends Application { private static final Logger logger = Logger.getLogger(Main.class.getName()); // TODO: get git info private static final String VERSION = "0.0.1"; private static Path statePath = null; public static Path getStatePath() { if (statePath == null) { String stateHome = System.getenv("XDG_STATE_HOME"); if (stateHome == null || stateHome.isEmpty() || !Paths.get(stateHome).isAbsolute()) { String userHome = System.getProperty("user.home"); statePath = Paths.get(userHome, ".local", "state", "numbers-station"); } else { statePath = Paths.get(stateHome, "numbers-station"); } } return statePath; } @Override public void start(Stage primaryStage) throws Exception { try { Parent root = FXMLLoader.load(getClass().getResource("MainView.fxml")); primaryStage.setTitle("Numbers Station"); primaryStage.setScene(new Scene(root)); primaryStage.show(); logger.info("Application started"); } catch (IOException e) { logger.log(Level.SEVERE, "Failed to load main view", e); } } private static void setupLogger() { try { Path logFile = getStatePath().resolve("main.log"); if (!Files.exists(logFile.getParent())) { Files.createDirectories(logFile.getParent()); } FileHandler fileHandler = new FileHandler(logFile.toString(), true); fileHandler.setFormatter(new CustomFormatter()); logger.addHandler(fileHandler); } catch (IOException e) { System.out.println("Failed to set up logger: " + e.getMessage()); } } public static void main(String[] args) { MainParsedArguments parsedArgs = new MainParsedArguments(args); if (parsedArgs.getHelpFlag()) { parsedArgs.printHelp(); System.exit(0); } if (parsedArgs.getVersionFlag()) { System.out.println("Numbers Station version " + VERSION); System.exit(0); } Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> { logger.log(Level.SEVERE, "Unhandled exception caught", throwable); }); Platform.setImplicitExit(false); Thread.currentThread().setUncaughtExceptionHandler((thread, throwable) -> { logger.log(Level.SEVERE, "Unhandled exception in JavaFX application thread", throwable); }); setupLogger(); if (parsedArgs.getStationName() != null) { // TODO: errors in runStation should trigger a notification runStation(parsedArgs); } else { launch(args); } } public static void runStation(MainParsedArguments parsedArgs) { if (parsedArgs.getStationName() == null || parsedArgs.getStationName() == "") { logger.log(Level.SEVERE, "Station name must be provided and not empty"); // TODO: Notification System.exit(1); } Result result = MainSettings.load(); if (!result.hasSuccess()) { logger.log(Level.SEVERE, "Unable to load settings"); // TODO: Notification System.exit(1); } MainSettings settings = result.getSuccess().get(); StationSettings loadedStation = settings.getStations().stream() .filter(station -> station.getName().equals(parsedArgs.getStationName())) .findFirst() .orElse(null); if (loadedStation == null) { logger.log(Level.SEVERE, "Unable to find station " + parsedArgs.getStationName()); // TODO: Notification System.exit(1); } logger.info("Loaded station " + parsedArgs.getStationName()); Path stationDirPath = loadedStation.stationPath(); try { boolean generateMessage = false; if (!Files.exists(stationDirPath)) { Files.createDirectories(stationDirPath); } Path nextMessagePath = stationDirPath.resolve("next-message.txt"); String messageText; if (!Files.exists(nextMessagePath)) { messageText = loadedStation.generateMessage(settings.getMessageGenerationAttempts()); } else { messageText = new String(Files.readAllBytes(nextMessagePath)); } // Send message using appropriate method switch (loadedStation.getMessageMethod()) { case StationSettings.MessageMethod.SFTP: //loadedStation.uploadNextMessageToSFTP(); break; case StationSettings.MessageMethod.WORDPRESS: SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); String dateStr = dateFormat.format(new Date()); System.setProperty("wordpress.username", loadedStation.getUsername()); System.setProperty("wordpress.password", loadedStation.getPassword()); System.setProperty("wordpress.url", loadedStation.getAddress()); Post post = new Post(dateStr, messageText); WordpressClient client = new WordpressClient(); String newPostId = client.newPost(post); break; default: logger.log(Level.SEVERE, "Message method " + loadedStation.getMessageMethod() + " not supported"); // TODO: Notification System.exit(1); } String newMessageText = loadedStation.generateMessage(settings.getMessageGenerationAttempts()); Files.write(nextMessagePath, newMessageText.getBytes(StandardCharsets.UTF_8)); } catch (IOException | StationSettings.MessageGenerationException e) { logger.log(Level.SEVERE, "Exception while posting message to station " + parsedArgs.getStationName(), e); // TODO: Notification System.exit(1); } System.exit(0); } }