summary refs log tree commit diff homepage
path: root/src/cli.cr
diff options
context:
space:
mode:
Diffstat (limited to 'src/cli.cr')
-rw-r--r--src/cli.cr118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/cli.cr b/src/cli.cr
new file mode 100644
index 0000000..5815c88
--- /dev/null
+++ b/src/cli.cr
@@ -0,0 +1,118 @@
+# Command-line interface
+# Copyright (C) 2023  Nguyễn Gia Phong
+#
+# This file if part of hybring.
+#
+# Hybring is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Hybring is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with hybring.  If not, see <https://www.gnu.org/licenses/>.
+
+require "ini"
+require "option_parser"
+
+require "./http"
+
+enum Subcommand
+  Serve
+  Usage
+end
+
+struct Configuration
+  @db : Path
+  getter db
+  @api : String
+  getter api
+  @opennic_local : Path
+  getter opennic_local
+  @opennic_remote : String
+  getter opennic_remote
+  @icann_local : Path
+  getter icann_local
+  @icann_remote : String
+  getter icann_remote
+
+  def initialize(path)
+    ini = INI.parse File.read path
+    @db = Path[ini["general"]["db"]]
+    @api = ini["general"]["api"]
+    @opennic_local = Path[ini["opennic"]["local"]]
+    @opennic_remote = ini["opennic"]["remote"]
+    @icann_local = Path[ini["icann"]["local"]]
+    @icann_remote = ini["icann"]["remote"]
+  end
+end
+
+subcmd = Subcommand::Usage
+usage = ""
+config_path, port = nil, 8910
+
+parser = OptionParser.new do |parser|
+  banner_prefix = "usage: #{Path[PROGRAM_NAME].basename}"
+  parser.banner = "#{banner_prefix} [subcommand] [arguments]"
+  parser.on "serve", "start the HTTP server"  do
+    subcmd = Subcommand::Serve
+    parser.banner = "#{banner_prefix} serve --config=PATH [--port=N]"
+    usage = parser.to_s
+    parser.on "-c PATH", "--config=PATH",
+              "path to configuration file (required)" do |path|
+      config_path = path
+    end
+    parser.on "-p N", "--port=N", "listening port (default to 8910)" do |n|
+      port = n.to_i
+    end
+  end
+  parser.on "-h", "--help", "show this help message and exit"  do
+    puts parser
+    exit
+  end
+
+  parser.invalid_option do |flag|
+    STDERR.puts "error: invalid option: #{flag}"
+    subcmd = Subcommand::Usage
+  end
+  parser.missing_option do |flag|
+    STDERR.puts "error: missing argument for #{flag}"
+    subcmd = Subcommand::Usage
+  end
+  parser.unknown_args do |before_dash, after_dash|
+    next if before_dash.empty? && after_dash.empty?
+    STDERR << "error: unknown arguments:"
+    STDERR << " " << before_dash.join " "  if !before_dash.empty?
+    STDERR << " -- " << after_dash.join " "  if !after_dash.empty?
+    STDERR.puts
+    subcmd = Subcommand::Usage
+  end
+end
+
+parser.parse
+cfg = case subcmd
+      when .serve?
+        unless config_path
+          STDERR << usage
+          exit 1
+        end
+        begin
+          Configuration.new config_path.not_nil!
+        rescue ex
+          STDERR.puts "error: failed to read config from #{config_path}: #{ex}"
+          exit 1
+        end
+      end
+
+case subcmd
+in .serve?
+  server = Server.new cfg.not_nil!
+  server.listen port
+in .usage?
+  STDERR.puts parser
+  exit 1
+end