meshchat 0.8.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +39 -11
- data/lib/meshchat.rb +48 -42
- data/lib/meshchat/configuration.rb +14 -0
- data/lib/meshchat/configuration/app_config.rb +63 -0
- data/lib/meshchat/configuration/database.rb +41 -0
- data/lib/meshchat/{config → configuration}/hash_file.rb +7 -6
- data/lib/meshchat/configuration/identity.rb +79 -0
- data/lib/meshchat/{config → configuration}/settings.rb +22 -26
- data/lib/meshchat/debug.rb +69 -0
- data/lib/meshchat/encryption.rb +7 -2
- data/lib/meshchat/encryption/aes_rsa.rb +2 -1
- data/lib/meshchat/encryption/passthrough.rb +5 -3
- data/lib/meshchat/locale/en.yml +14 -0
- data/lib/meshchat/models/node.rb +140 -0
- data/lib/meshchat/network.rb +19 -0
- data/lib/meshchat/network/dispatcher.rb +83 -0
- data/lib/meshchat/network/errors.rb +11 -0
- data/lib/meshchat/network/incoming.rb +13 -0
- data/lib/meshchat/network/incoming/message_decryptor.rb +51 -0
- data/lib/meshchat/network/incoming/message_processor.rb +75 -0
- data/lib/meshchat/network/incoming/request_processor.rb +30 -0
- data/lib/meshchat/network/local.rb +12 -0
- data/lib/meshchat/network/local/connection.rb +58 -0
- data/lib/meshchat/network/local/server.rb +69 -0
- data/lib/meshchat/network/message.rb +34 -0
- data/lib/meshchat/network/message/base.rb +139 -0
- data/lib/meshchat/network/message/chat.rb +9 -0
- data/lib/meshchat/network/message/disconnect.rb +21 -0
- data/lib/meshchat/network/message/emote.rb +9 -0
- data/lib/meshchat/network/message/factory.rb +80 -0
- data/lib/meshchat/network/message/node_list.rb +75 -0
- data/lib/meshchat/network/message/node_list_diff.rb +18 -0
- data/lib/meshchat/network/message/node_list_hash.rb +32 -0
- data/lib/meshchat/network/message/ping.rb +31 -0
- data/lib/meshchat/network/message/ping_reply.rb +12 -0
- data/lib/meshchat/network/message/whisper.rb +28 -0
- data/lib/meshchat/network/remote.rb +13 -0
- data/lib/meshchat/network/remote/connection.rb +28 -0
- data/lib/meshchat/network/remote/relay.rb +109 -0
- data/lib/meshchat/network/remote/relay_pool.rb +52 -0
- data/lib/meshchat/ui.rb +13 -0
- data/lib/meshchat/ui/cli.rb +48 -0
- data/lib/meshchat/ui/cli/base.rb +39 -0
- data/lib/meshchat/ui/cli/input_factory.rb +50 -0
- data/lib/meshchat/ui/cli/keyboard_line_input.rb +14 -0
- data/lib/meshchat/ui/command.rb +51 -0
- data/lib/meshchat/ui/command/base.rb +77 -0
- data/lib/meshchat/ui/command/bind.rb +47 -0
- data/lib/meshchat/ui/command/chat.rb +31 -0
- data/lib/meshchat/ui/command/config.rb +37 -0
- data/lib/meshchat/ui/command/emote.rb +23 -0
- data/lib/meshchat/ui/command/exit.rb +16 -0
- data/lib/meshchat/ui/command/help.rb +20 -0
- data/lib/meshchat/ui/command/identity.rb +16 -0
- data/lib/meshchat/ui/command/import.rb +42 -0
- data/lib/meshchat/ui/command/irb.rb +22 -0
- data/lib/meshchat/ui/command/offline.rb +23 -0
- data/lib/meshchat/ui/command/online.rb +18 -0
- data/lib/meshchat/ui/command/ping.rb +65 -0
- data/lib/meshchat/ui/command/ping_all.rb +19 -0
- data/lib/meshchat/ui/command/send_disconnect.rb +20 -0
- data/lib/meshchat/ui/command/server.rb +22 -0
- data/lib/meshchat/ui/command/share.rb +16 -0
- data/lib/meshchat/ui/command/whisper.rb +40 -0
- data/lib/meshchat/ui/display.rb +78 -0
- data/lib/meshchat/ui/display/base.rb +58 -0
- data/lib/meshchat/ui/display/manager.rb +59 -0
- data/lib/meshchat/ui/notifier.rb +9 -0
- data/lib/meshchat/ui/notifier/base.rb +33 -0
- data/lib/meshchat/version.rb +3 -2
- metadata +150 -80
- data/lib/meshchat/cli.rb +0 -188
- data/lib/meshchat/cli/base.rb +0 -13
- data/lib/meshchat/cli/input.rb +0 -37
- data/lib/meshchat/command/base.rb +0 -80
- data/lib/meshchat/command/bind.rb +0 -44
- data/lib/meshchat/command/chat.rb +0 -30
- data/lib/meshchat/command/config.rb +0 -34
- data/lib/meshchat/command/emote.rb +0 -20
- data/lib/meshchat/command/exit.rb +0 -13
- data/lib/meshchat/command/help.rb +0 -17
- data/lib/meshchat/command/identity.rb +0 -13
- data/lib/meshchat/command/import.rb +0 -41
- data/lib/meshchat/command/init.rb +0 -34
- data/lib/meshchat/command/irb.rb +0 -23
- data/lib/meshchat/command/listen.rb +0 -13
- data/lib/meshchat/command/offline.rb +0 -20
- data/lib/meshchat/command/online.rb +0 -15
- data/lib/meshchat/command/ping.rb +0 -65
- data/lib/meshchat/command/ping_all.rb +0 -15
- data/lib/meshchat/command/send_disconnect.rb +0 -15
- data/lib/meshchat/command/server.rb +0 -20
- data/lib/meshchat/command/share.rb +0 -13
- data/lib/meshchat/command/stop_listening.rb +0 -13
- data/lib/meshchat/command/whisper.rb +0 -38
- data/lib/meshchat/database.rb +0 -30
- data/lib/meshchat/display.rb +0 -33
- data/lib/meshchat/display/base.rb +0 -60
- data/lib/meshchat/display/manager.rb +0 -55
- data/lib/meshchat/instance.rb +0 -40
- data/lib/meshchat/message.rb +0 -41
- data/lib/meshchat/message/base.rb +0 -97
- data/lib/meshchat/message/chat.rb +0 -19
- data/lib/meshchat/message/disconnect.rb +0 -13
- data/lib/meshchat/message/emote.rb +0 -9
- data/lib/meshchat/message/node_list.rb +0 -63
- data/lib/meshchat/message/node_list_diff.rb +0 -15
- data/lib/meshchat/message/node_list_hash.rb +0 -33
- data/lib/meshchat/message/ping.rb +0 -32
- data/lib/meshchat/message/ping_reply.rb +0 -9
- data/lib/meshchat/message/relay.rb +0 -43
- data/lib/meshchat/message/whisper.rb +0 -36
- data/lib/meshchat/models/entry.rb +0 -104
- data/lib/meshchat/net/client.rb +0 -83
- data/lib/meshchat/net/listener/errors.rb +0 -11
- data/lib/meshchat/net/listener/request.rb +0 -48
- data/lib/meshchat/net/listener/request_processor.rb +0 -50
- data/lib/meshchat/net/listener/server.rb +0 -114
- data/lib/meshchat/net/request.rb +0 -29
- data/lib/meshchat/notifier/base.rb +0 -31
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Meshchat
|
3
|
+
module Network
|
4
|
+
module Remote
|
5
|
+
class RelayPool
|
6
|
+
# This channel is determine by the server, see
|
7
|
+
# https://github.com/NullVoxPopuli/mesh-relay/blob/master/app/channels/mesh_relay_channel.rb
|
8
|
+
CHANNEL = 'MeshRelayChannel'
|
9
|
+
|
10
|
+
attr_accessor :_message_dispatcher
|
11
|
+
attr_accessor :_active_relay
|
12
|
+
attr_accessor :_known_relays, :_available_relays
|
13
|
+
|
14
|
+
def initialize(message_dispatcher)
|
15
|
+
@_message_dispatcher = message_dispatcher
|
16
|
+
@_known_relays = APP_CONFIG.user['relays'] || []
|
17
|
+
@_available_relays = APP_CONFIG.user['relays'] || []
|
18
|
+
|
19
|
+
find_initial_relay if @_known_relays.present?
|
20
|
+
end
|
21
|
+
|
22
|
+
# TODO: add logic for just selecting the first available relay.
|
23
|
+
# we only need one connection.
|
24
|
+
# @return [Array] an array of action cable clients
|
25
|
+
def find_initial_relay(connected: nil)
|
26
|
+
url = _known_relays.first
|
27
|
+
@_active_relay = Relay.new(
|
28
|
+
url, _message_dispatcher,
|
29
|
+
connected: connected)
|
30
|
+
end
|
31
|
+
|
32
|
+
# @param [Hash] payload - the message payload
|
33
|
+
def send_payload(payload)
|
34
|
+
return if _active_relay.blank?
|
35
|
+
|
36
|
+
ensure_active_connection! do
|
37
|
+
_active_relay.perform('chat', payload)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def ensure_active_connection!(&block)
|
42
|
+
# TODO: make action_cable_client return a boolean
|
43
|
+
if !_active_relay.connected?
|
44
|
+
find_initial_relay(connected: block)
|
45
|
+
else
|
46
|
+
yield
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/meshchat/ui.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Meshchat
|
3
|
+
module Ui
|
4
|
+
# A user interface is responsible for for creating a client
|
5
|
+
# and sending messages to that client
|
6
|
+
class CLI
|
7
|
+
extend ActiveSupport::Autoload
|
8
|
+
|
9
|
+
eager_autoload do
|
10
|
+
autoload :InputFactory
|
11
|
+
autoload :Base
|
12
|
+
autoload :KeyboardLineInput
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :_message_dispatcher, :_message_factory, :_command_factory
|
16
|
+
|
17
|
+
def initialize(dispatcher, message_factory, _display)
|
18
|
+
@_message_dispatcher = dispatcher
|
19
|
+
@_message_factory = message_factory
|
20
|
+
@_command_factory = InputFactory.new(dispatcher, message_factory, self)
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_input(msg)
|
24
|
+
handler = _command_factory.create(for_input: msg)
|
25
|
+
handler.handle
|
26
|
+
rescue => e
|
27
|
+
Debug.creating_input_failed(e)
|
28
|
+
end
|
29
|
+
|
30
|
+
# save config and exit
|
31
|
+
def shutdown
|
32
|
+
# close_server
|
33
|
+
Display.info 'saving config...'
|
34
|
+
APP_CONFIG.user.save
|
35
|
+
Display.info 'notifying of disconnection...'
|
36
|
+
send_disconnect
|
37
|
+
Display.alert "\n\nGoodbye. \n\nThank you for using #{Meshchat.name}"
|
38
|
+
exit
|
39
|
+
end
|
40
|
+
|
41
|
+
def send_disconnect
|
42
|
+
klass = Command::SendDisconnect
|
43
|
+
command = _command_factory.create(with_class: klass)
|
44
|
+
command.handle
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Meshchat
|
3
|
+
module Ui
|
4
|
+
class CLI
|
5
|
+
# this class, and all subclasses are Keyboard Handlers
|
6
|
+
# that are used for EventMachine's open_keyboard
|
7
|
+
# @see https://github.com/eventmachine/eventmachine/wiki/Code-Snippets#keyboard-input-example
|
8
|
+
class Base < EventMachine::Connection
|
9
|
+
# The class used for interpeting the line input
|
10
|
+
attr_reader :_input_receiver
|
11
|
+
# An array of typed keystrokes
|
12
|
+
attr_reader :_input_buffer
|
13
|
+
|
14
|
+
def initialize(input_receiver)
|
15
|
+
@_input_receiver = input_receiver
|
16
|
+
@_input_buffer = []
|
17
|
+
end
|
18
|
+
|
19
|
+
# override this method to alter how input is
|
20
|
+
# interpreted by the receiver.
|
21
|
+
#
|
22
|
+
# hopefully, just by calling a different method
|
23
|
+
# on the receiver, as input processing shouldn't
|
24
|
+
# occurr in this class or any subclass unless it is
|
25
|
+
# raw keystroke input
|
26
|
+
#
|
27
|
+
# @note that this method receives raw keystrokes by default
|
28
|
+
# and does not send data to the input receiver
|
29
|
+
def receive_data(data)
|
30
|
+
_input_buffer.push(data)
|
31
|
+
end
|
32
|
+
|
33
|
+
def receive_line(line)
|
34
|
+
# only used when including EM::Protocols::LineText2
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Meshchat
|
3
|
+
module Ui
|
4
|
+
class CLI
|
5
|
+
class InputFactory
|
6
|
+
WHISPER = '@'
|
7
|
+
COMMAND = '/'
|
8
|
+
|
9
|
+
attr_accessor :_message_dispatcher, :_message_factory, :_cli
|
10
|
+
|
11
|
+
def initialize(message_dispatcher, message_factory, cli)
|
12
|
+
self._message_dispatcher = message_dispatcher
|
13
|
+
self._message_factory = message_factory
|
14
|
+
self._cli = cli
|
15
|
+
end
|
16
|
+
|
17
|
+
def is_command?(input)
|
18
|
+
input[0, 1] == COMMAND
|
19
|
+
end
|
20
|
+
|
21
|
+
def is_whisper?(input)
|
22
|
+
input[0, 1] == WHISPER
|
23
|
+
end
|
24
|
+
|
25
|
+
def create(for_input: nil, with_class: nil)
|
26
|
+
return create_with_class(for_input, with_class) if with_class
|
27
|
+
|
28
|
+
create_for_input(for_input)
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_with_class(input, klass)
|
32
|
+
klass.new(input, _message_dispatcher, _message_factory, self)
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_for_input(input)
|
36
|
+
klass =
|
37
|
+
if is_command?(input)
|
38
|
+
Command::Base
|
39
|
+
elsif is_whisper?(input)
|
40
|
+
Command::Whisper
|
41
|
+
else
|
42
|
+
Command::Chat
|
43
|
+
end
|
44
|
+
|
45
|
+
create_with_class(input, klass)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Meshchat
|
3
|
+
module Ui
|
4
|
+
module Command
|
5
|
+
extend ActiveSupport::Autoload
|
6
|
+
|
7
|
+
eager_autoload do
|
8
|
+
autoload :Base
|
9
|
+
autoload :Chat
|
10
|
+
autoload :Identity
|
11
|
+
autoload :Irb
|
12
|
+
autoload :Config
|
13
|
+
autoload :Ping
|
14
|
+
autoload :PingAll
|
15
|
+
autoload :Server
|
16
|
+
autoload :Whisper
|
17
|
+
autoload :Exit
|
18
|
+
autoload :SendDisconnect
|
19
|
+
autoload :Help
|
20
|
+
autoload :Bind
|
21
|
+
autoload :Online
|
22
|
+
autoload :Offline
|
23
|
+
autoload :Share
|
24
|
+
autoload :Import
|
25
|
+
autoload :Emote
|
26
|
+
end
|
27
|
+
|
28
|
+
COMMAND_MAP = {
|
29
|
+
Base::CONFIG => Config,
|
30
|
+
Base::PING => Ping,
|
31
|
+
Base::PING_ALL => PingAll,
|
32
|
+
Base::SERVERS => Server,
|
33
|
+
Base::SERVER => Server,
|
34
|
+
Base::EXIT => Exit,
|
35
|
+
Base::QUIT => Exit,
|
36
|
+
Base::IDENTITY => Identity,
|
37
|
+
Base::IRB => Irb,
|
38
|
+
Base::SHARE => Share,
|
39
|
+
Base::IMPORT => Import,
|
40
|
+
Base::EXPORT => Share,
|
41
|
+
Base::ONLINE => Online,
|
42
|
+
Base::OFFLINE => Offline,
|
43
|
+
Base::HELP => Help,
|
44
|
+
Base::BIND => Bind,
|
45
|
+
Base::SEND_DISCONNECT => SendDisconnect,
|
46
|
+
Base::EMOTE => Emote,
|
47
|
+
Base::CHAT => Chat
|
48
|
+
}.freeze
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Meshchat
|
3
|
+
module Ui
|
4
|
+
module Command
|
5
|
+
class Base
|
6
|
+
# Commands
|
7
|
+
SET = 'set'
|
8
|
+
CONFIG = 'config'
|
9
|
+
DISPLAY = 'display'
|
10
|
+
EXIT = 'exit'
|
11
|
+
QUIT = 'quit'
|
12
|
+
CHAT = 'chat'
|
13
|
+
ADD = 'add'
|
14
|
+
REMOVE = 'remove'
|
15
|
+
RM = 'rm'
|
16
|
+
SERVERS = 'servers'
|
17
|
+
SERVER = 'server'
|
18
|
+
WHO = 'who'
|
19
|
+
PING = 'ping'
|
20
|
+
PING_ALL = 'pingall'
|
21
|
+
IDENTITY = 'identity'
|
22
|
+
IRB = 'c'
|
23
|
+
SHARE = 'share'
|
24
|
+
IMPORT = 'import'
|
25
|
+
EXPORT = 'export'
|
26
|
+
ONLINE = 'online'
|
27
|
+
OFFLINE = 'offline'
|
28
|
+
HELP = 'help'
|
29
|
+
BIND = 'bind'
|
30
|
+
SEND_DISCONNECT = 'senddisconnect'
|
31
|
+
EMOTE = 'me'
|
32
|
+
|
33
|
+
attr_reader :_input, :_message_dispatcher
|
34
|
+
attr_reader :_message_factory, :_input_factory
|
35
|
+
|
36
|
+
def initialize(input, message_dispatcher, message_factory, input_factory)
|
37
|
+
@_input = input&.chomp
|
38
|
+
@_message_dispatcher = message_dispatcher
|
39
|
+
@_message_factory = message_factory
|
40
|
+
@_input_factory = input_factory
|
41
|
+
end
|
42
|
+
|
43
|
+
def handle
|
44
|
+
klass = COMMAND_MAP[command]
|
45
|
+
Display.debug("INPUT: #{klass&.name} from #{command} derived from #{_input}")
|
46
|
+
if klass
|
47
|
+
_input_factory.create(for_input: _input, with_class: klass).handle
|
48
|
+
else
|
49
|
+
Display.alert 'not implemented...'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
def command_string
|
56
|
+
@command_string ||= _input[1, _input.length]
|
57
|
+
end
|
58
|
+
|
59
|
+
def command_args
|
60
|
+
@command_args ||= command_string.split(' ')
|
61
|
+
end
|
62
|
+
|
63
|
+
def command
|
64
|
+
@command ||= command_args.first
|
65
|
+
end
|
66
|
+
|
67
|
+
def sub_command_args
|
68
|
+
@sub_command_args ||= command_args[2..3]
|
69
|
+
end
|
70
|
+
|
71
|
+
def sub_command
|
72
|
+
@sub_command ||= command_args[1]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'socket'
|
3
|
+
require 'open-uri'
|
4
|
+
|
5
|
+
module Meshchat
|
6
|
+
module Ui
|
7
|
+
module Command
|
8
|
+
class Bind < Command::Base
|
9
|
+
def self.description
|
10
|
+
'helper for choosing what ip address to use for yourself'
|
11
|
+
end
|
12
|
+
|
13
|
+
def handle
|
14
|
+
options = ip_addresses
|
15
|
+
option_numbers = []
|
16
|
+
Display.success 'Choose an ip:'
|
17
|
+
options.each_with_index do |ip, index|
|
18
|
+
Display.info "#{index}: #{ip}"
|
19
|
+
option_numbers << index
|
20
|
+
end
|
21
|
+
|
22
|
+
selected = gets
|
23
|
+
|
24
|
+
if option_numbers.include?(selected.to_i)
|
25
|
+
Display.success Settings.set('ip', with: options[selected.to_i])
|
26
|
+
else
|
27
|
+
Display.alert 'Invalid selection'
|
28
|
+
handle # repeat
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def ip_addresses
|
33
|
+
local = Socket.getifaddrs.map { |i| i.addr.ip_address if i.addr.ipv4? }.compact
|
34
|
+
# get public
|
35
|
+
begin
|
36
|
+
remote_ip = open('http://whatismyip.akamai.com').read
|
37
|
+
local << remote_ip
|
38
|
+
rescue => e
|
39
|
+
Display.fatal e.message
|
40
|
+
Display.alert 'public ip lookup failed'
|
41
|
+
end
|
42
|
+
local
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Meshchat
|
3
|
+
module Ui
|
4
|
+
module Command
|
5
|
+
class Chat < Command::Base
|
6
|
+
def handle
|
7
|
+
servers = Node.online
|
8
|
+
if !servers.empty?
|
9
|
+
type = self.class.name.demodulize.downcase
|
10
|
+
m = _message_factory.create(type, data: { message: _input })
|
11
|
+
show_myself(m)
|
12
|
+
|
13
|
+
# if sending to all, iterate thorugh list of
|
14
|
+
# servers, and send to each one
|
15
|
+
# TODO: do this async so that one server doesn't block
|
16
|
+
# the rest of the servers from receiving the messages
|
17
|
+
servers.each do |entry|
|
18
|
+
_message_dispatcher.send_message(node: entry, message: m)
|
19
|
+
end
|
20
|
+
else
|
21
|
+
Display.warning 'you have no servers'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def show_myself(message)
|
26
|
+
Display.chat message.display
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Meshchat
|
3
|
+
module Ui
|
4
|
+
module Command
|
5
|
+
class Config < Command::Base
|
6
|
+
def self.description
|
7
|
+
'interface for setting and displaying various config options'
|
8
|
+
end
|
9
|
+
|
10
|
+
def handle
|
11
|
+
case sub_command
|
12
|
+
when SET
|
13
|
+
if is_valid_set_command?
|
14
|
+
key, value = config_set_args
|
15
|
+
|
16
|
+
Display.info APP_CONFIG.user.set(key, with: value)
|
17
|
+
else
|
18
|
+
Display.alert 'set requires a key and a value'
|
19
|
+
end
|
20
|
+
when DISPLAY
|
21
|
+
Display.info APP_CONFIG.user.display
|
22
|
+
else
|
23
|
+
Display.alert 'config command not implemented...'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def config_set_args
|
28
|
+
command_args[2..3]
|
29
|
+
end
|
30
|
+
|
31
|
+
def is_valid_set_command?
|
32
|
+
sub_command == SET && command_args.length == 4
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|