package moe.kyokobot.backend; import com.mewna.catnip.Catnip; import io.micronaut.runtime.Micronaut; import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; import moe.kyokobot.shared.Banner; import moe.kyokobot.shared.Settings; import moe.kyokobot.shared.util.JsonUtil; import moe.kyokobot.shared.util.Signer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; public class Main { private static final Logger logger = LoggerFactory.getLogger(Main.class); private static String config; private static Signer signer; private static Catnip catnip; static { System.setProperty("vertx.logger-delegate-factory-class-name", "io.vertx.core.logging.SLF4JLogDelegateFactory"); String config = System.getenv("KYOKO_CONFIG"); if (config == null) config = System.getProperty("kyoko.config", "config.json"); Main.config = config; } public static void main(String[] args) { Banner.show(logger, "Kyoko backend service"); loadSettings(); catnip = configureCatnip(); Micronaut.run(Main.class); } private static Catnip configureCatnip() { var token = Settings.instance().apiKeys().get("discord"); var vertx = Vertx.vertx(new VertxOptions().setEventLoopPoolSize(1)); return Catnip.catnip(token, vertx); } private static void loadSettings() { Settings settings; var cfg = Path.of(config); var keyFile = Path.of("keyfile.bin"); if (!Files.exists(cfg)) { logger.error("No configuration file found, run kyokobot.jar to generate a new one!"); } if (Files.exists(keyFile)) { try { signer = new Signer(Files.readAllBytes(keyFile)); } catch (IOException e) { logger.error("Cannot read keyfile!", e); System.exit(1); } } else { try { logger.info("Generating new keyfile..."); var key = new byte[256]; SecureRandom.getInstanceStrong().nextBytes(key); Files.write(keyFile, key); signer = new Signer(key); } catch (NoSuchAlgorithmException | IOException e) { logger.error("Error generating keyfile", e); System.exit(1); } } try (var fis = Files.newInputStream(cfg)) { settings = JsonUtil.fromJSON(fis, Settings.class); Settings.instance(settings); } catch (IOException e) { logger.error("Cannot read configuration file!", e); System.exit(1); return; } if (settings.apiKeys() == null || !settings.apiKeys().containsKey("discord")) { logger.error("No token specified! Please add a \"discord\" key with the token as value into \"api-keys\" " + "entry in the configuration file"); System.exit(1); return; } if (settings.apiKeys() == null || !settings.apiKeys().containsKey("discord_client")) { logger.error("No client secret specified! Please add a \"discord_client\" key with the token as value " + "into \"api-keys\" entry in the configuration file"); System.exit(1); } } public static Catnip getCatnip() { return catnip; } public static Signer getSigner() { return signer; } }