summary refs log tree commit diff homepage
path: root/src/cli.cr
blob: ecec1f8b5817572eb3f8129587a6c5da40f603ae (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# 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
  @sock : String
  getter sock
  @db : Path
  getter db
  @css : Path
  getter css

  @opennic_local : Path
  getter opennic_local
  @opennic_remote : String
  getter opennic_remote
  @opennic_api : String
  getter opennic_api

  @icann_local : Path
  getter icann_local
  @icann_remote : String
  getter icann_remote
  @icann_api : String
  getter icann_api

  def initialize(ini)
    @sock = ini["general"]["sock"]
    @db = Path[ini["general"]["db"]]
    @css = Path[ini["general"]["css"]]

    @opennic_local = Path[ini["opennic"]["local"]]
    @opennic_remote = ini["opennic"]["remote"]
    @opennic_api = ini["opennic"]["api"]

    @icann_local = Path[ini["icann"]["local"]]
    @icann_remote = ini["icann"]["remote"]
    @icann_api = ini["icann"]["api"]
  end
end

def die(error)
  STDERR << error
  exit 1
end

{% unless @top_level.constant("SPEC") %}
  subcmd = Subcommand::Usage
  usage = ""
  config_path, port = nil, 0

  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" 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
            die usage
          end
          begin
            Configuration.new INI.parse File.read config_path.not_nil!
          rescue ex
            die "Error: Failed to read config from #{config_path}: #{ex}\n"
          end
        end

  case subcmd
  in .serve?
    server = Server.new cfg.not_nil!
    server.listen port do |address|
      puts "Listening on #{address}"
    end
  in .usage?
    die parser
  end
{% end %}