meshchat 0.11.2 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 769222556d02960c10f6e09f5216979a9d3b99b0
4
- data.tar.gz: d2fb3690c939227b155933e7f404cea22b4a8ab4
3
+ metadata.gz: 677204be2321055039fb7d40db56bf98240b65c5
4
+ data.tar.gz: 7183a0315be9faa2f4730c3a6f3c5d718ae184b6
5
5
  SHA512:
6
- metadata.gz: 5cf9b9d8a513a1a1e92e8e8b7afb1ada009dad234a3a935cc846b7bab8f34ced4539dbf643444b3c393ac6e9d5ee4309ea81b90b3da58956037dde9d355e6d2f
7
- data.tar.gz: 273717543e8ec2081d2d2e7545da2fcea27eb398e7297eceb3f8a4a8976a86ce7f9f8c82d59772af1b4a42ff802de2af4caa476e90c0af0d2d7cb7122ea3d819
6
+ metadata.gz: cdf0dfc6e780ce78e04f0986ea82c895e3ced5a76ef0e69184e655aa5d2e3d411a5a53505fdc5f127d3e1820c75f053f15c72fd928eb8f6c23badc5fb1da3853
7
+ data.tar.gz: 78e642349854b82423d953819e49f326046b5096f3c876611acdc12e1e5584cd98ae1c62d886f044867bf8176f4d247d88621dc009ed2467a54683ad9cdcdd1a
@@ -31,6 +31,8 @@ module Meshchat
31
31
 
32
32
  table.column :on_local_network, :boolean, default: true, null: false
33
33
  table.column :on_relay, :boolean, default: false, null: false
34
+
35
+ table.timestamps
34
36
  end
35
37
  end
36
38
  end
@@ -12,3 +12,4 @@ identity:
12
12
  current_alias: 'Your current name/alias is: %{name}'
13
13
  node:
14
14
  not_found: "Node not found, or does not have a location. Have you imported %{name}?"
15
+ multiple_with_alias: "!! You know multiple people named '%{name}', which would you like to send to?"
@@ -22,6 +22,10 @@ module Meshchat
22
22
 
23
23
  @_to = to
24
24
  end
25
+
26
+ def display
27
+ super.merge(to: _to)
28
+ end
25
29
  end
26
30
  end
27
31
  end
@@ -7,6 +7,7 @@ module Meshchat
7
7
  COMMAND = '/'
8
8
 
9
9
  attr_accessor :_message_dispatcher, :_message_factory, :_cli
10
+ attr_accessor :_whisper_lock_target
10
11
 
11
12
  def initialize(message_dispatcher, message_factory, cli)
12
13
  self._message_dispatcher = message_dispatcher
@@ -32,6 +33,14 @@ module Meshchat
32
33
  klass.new(input, _message_dispatcher, _message_factory, self)
33
34
  end
34
35
 
36
+ def clear_whisper_lock
37
+ self._whisper_lock_target = nil
38
+ end
39
+
40
+ def whisper_lock_to(node)
41
+ self._whisper_lock_target = node
42
+ end
43
+
35
44
  def create_for_input(input)
36
45
  klass =
37
46
  if is_command?(input)
@@ -39,11 +48,20 @@ module Meshchat
39
48
  elsif is_whisper?(input)
40
49
  Command::Whisper
41
50
  else
51
+ return whisper_for_locked_target(input) if _whisper_lock_target
42
52
  Command::Chat
43
53
  end
44
54
 
45
55
  create_with_class(input, klass)
46
56
  end
57
+
58
+ def whisper_for_locked_target(input)
59
+ command = Command::Whisper.new(
60
+ input, _message_dispatcher, _message_factory, self)
61
+
62
+ command._target_node = _whisper_lock_target
63
+ command
64
+ end
47
65
  end
48
66
  end
49
67
  end
@@ -16,7 +16,18 @@ module Meshchat
16
16
 
17
17
  def initialize
18
18
  Readline.callback_handler_install('> ') do |line|
19
- EventMachine.next_tick { @input_receiver.create_input(line) }
19
+ EventMachine.next_tick { handle_input(line) }
20
+ end
21
+ end
22
+
23
+ def handle_input(line)
24
+ if @callback
25
+ # call and clear, so we can resume normal
26
+ # input handling
27
+ @callback.call(line)
28
+ @callback = nil
29
+ else
30
+ @input_receiver.create_input(line)
20
31
  end
21
32
  end
22
33
 
@@ -32,6 +43,10 @@ module Meshchat
32
43
  @input_receiver = receiver
33
44
  end
34
45
 
46
+ def callback_on_next_tick=(callback)
47
+ @callback = callback
48
+ end
49
+
35
50
  end
36
51
 
37
52
  class << self
@@ -40,6 +55,14 @@ module Meshchat
40
55
  aliases = Meshchat::Node.all.map { |n| "#{n.alias_name}" }
41
56
  commands + aliases
42
57
  end
58
+
59
+ def input_handler
60
+ @input_handler
61
+ end
62
+
63
+ def input_handler=(handler)
64
+ @input_handler = handler
65
+ end
43
66
  end
44
67
 
45
68
  def start
@@ -48,12 +71,13 @@ module Meshchat
48
71
  conn = EventMachine.watch $stdin, Handler
49
72
  conn.notify_readable = true
50
73
  conn.input_receiver = _input_receiver
51
-
74
+ self.class.input_handler = conn
52
75
  # update auto completion
53
76
  completion = proc { |s| self.class.autocompletes.grep(/^#{Regexp.escape(s)}/) }
54
77
  Readline.completion_proc = completion
55
78
  end
56
79
 
80
+
57
81
  # def initialize(*args)
58
82
  # super(args)
59
83
  #
@@ -7,13 +7,17 @@ module Meshchat
7
7
  eager_autoload do
8
8
  autoload :Base
9
9
  autoload :Chat
10
+ autoload :Emote
11
+ autoload :Whisper
12
+ autoload :WhisperLock
13
+ autoload :AllChatLock
14
+
10
15
  autoload :Identity
11
16
  autoload :Irb
12
17
  autoload :Config
13
18
  autoload :Ping
14
19
  autoload :PingAll
15
20
  autoload :Server
16
- autoload :Whisper
17
21
  autoload :Exit
18
22
  autoload :SendDisconnect
19
23
  autoload :Help
@@ -22,8 +26,10 @@ module Meshchat
22
26
  autoload :Offline
23
27
  autoload :Share
24
28
  autoload :Import
25
- autoload :Emote
26
29
  autoload :Roll
30
+
31
+ # Utility
32
+ autoload :NodeFinder
27
33
  end
28
34
 
29
35
  COMMAND_MAP = {
@@ -46,7 +52,9 @@ module Meshchat
46
52
  Base::SEND_DISCONNECT => SendDisconnect,
47
53
  Base::EMOTE => Emote,
48
54
  Base::ROLL => Roll,
49
- Base::CHAT => Chat
55
+ Base::CHAT => Chat,
56
+ Base::WHISPER_LOCK => WhisperLock,
57
+ Base::ALL_CHAT_LOCK => AllChatLock
50
58
  }.freeze
51
59
  end
52
60
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+ module Meshchat
3
+ module Ui
4
+ module Command
5
+ class AllChatLock < Command::Base
6
+ def self.description
7
+ 'sets the current chat to the "All Chat"'
8
+ end
9
+
10
+ def handle
11
+ return unless _input_factory._whisper_lock_target
12
+ Display.info 'whisper lock disabled'
13
+ _input_factory.clear_whisper_lock
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -30,6 +30,8 @@ module Meshchat
30
30
  SEND_DISCONNECT = 'senddisconnect'
31
31
  EMOTE = 'me'
32
32
  ROLL = 'roll'
33
+ WHISPER_LOCK = 'wl'
34
+ ALL_CHAT_LOCK = 'all'
33
35
 
34
36
  attr_reader :_input, :_message_dispatcher
35
37
  attr_reader :_message_factory, :_input_factory
@@ -47,7 +49,7 @@ module Meshchat
47
49
  if klass
48
50
  _input_factory.create(for_input: _input, with_class: klass).handle
49
51
  else
50
- Display.alert 'not implemented...'
52
+ Display.alert "#{command} not implemented..."
51
53
  end
52
54
  end
53
55
 
@@ -0,0 +1,58 @@
1
+ module Meshchat
2
+ module Ui
3
+ module Command
4
+ module NodeFinder
5
+ module_function
6
+
7
+ def find_by_target(string, &block)
8
+ search_key = string.start_with?('#') ? :uid : :alias_name
9
+ nodes = Node.where(search_key => string)
10
+ if nodes.length == 0
11
+ return Display.warning('No node by: ' + string)
12
+ end
13
+
14
+ return block.call(nodes.first) if nodes.length == 1
15
+
16
+ Display.warning I18n.t('node.multiple_with_alias', name: string)
17
+ ask_for_specification(nodes, block)
18
+ end
19
+
20
+ def ask_for_specification(nodes, block)
21
+ # there are now more than 1 nodes
22
+ display_nodes(nodes)
23
+
24
+
25
+ # insert a callback into the input handler to run the next
26
+ # time a line is received
27
+ #
28
+ # TODO: this feels gross, is there a better way?
29
+ # TODO: move this callback from ReadlineInput to the Input Base
30
+ CLI::ReadlineInput.input_handler.callback_on_next_tick = lambda do |line|
31
+ answer = line.to_i
32
+ node = nodes[answer]
33
+ # finally, send the mesasge
34
+ # (or do whatever this is)
35
+ # but usually, it sending the message
36
+ block.call(node)
37
+ end
38
+ end
39
+
40
+ def display_nodes(nodes)
41
+ # write header
42
+ Display.info "\t\t UID Last Seen"
43
+ Display.info '-' * 60
44
+
45
+ # write nodes
46
+ nodes.each_with_index do |node, index|
47
+ i = index.to_s
48
+ alias_name = node.alias_name
49
+ uid = node.uid[0..5]
50
+ last_seen = node.updated_at&.strftime('%B %e, %Y %H:%M:%S') || 'never'
51
+ line = "%-2s | %-15s %-8s %s" % [i, alias_name, uid, last_seen]
52
+ Display.info line
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -3,35 +3,48 @@ module Meshchat
3
3
  module Ui
4
4
  module Command
5
5
  class Whisper < Command::Base
6
+ attr_accessor :_target_node
7
+
6
8
  def self.description
7
9
  'sends a private message to a spepcific person'
8
10
  end
9
11
 
10
12
  def target
11
13
  # get first arg
14
+ return _target_node.alias_name if _target_node
12
15
  command
13
16
  end
14
17
 
15
18
  def message
19
+ return _input if _target_node
16
20
  command_args[1..command_args.length].try(:join, ' ')
17
21
  end
18
22
 
19
23
  def handle
20
- node = Node.find_by_alias_name(target)
24
+ return send_message_to_node(_target_node) if _target_node
25
+ find_node_and_whisper(target)
26
+ end
21
27
 
22
- if node
23
- m = _message_factory.create(
24
- Network::Message::WHISPER,
25
- data: {
26
- message: message,
27
- to: target
28
- })
28
+ def send_message_to_node(node)
29
+ m = _message_factory.create(
30
+ Network::Message::WHISPER,
31
+ data: {
32
+ message: message,
33
+ to: target
34
+ })
29
35
 
30
- Display.whisper m.display
36
+ Display.whisper m.display
37
+
38
+ _message_dispatcher.send_message(node: node, message: m)
39
+ end
31
40
 
32
- _message_dispatcher.send_message(node: node, message: m)
33
- else
34
- Display.alert "node for #{target} not found or is not online"
41
+ def find_node_and_whisper(target)
42
+ NodeFinder.find_by_target(target) do |node|
43
+ if node
44
+ send_message_to_node(node)
45
+ else
46
+ Display.alert "node for #{target} not found or is not online"
47
+ end
35
48
  end
36
49
  end
37
50
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+ module Meshchat
3
+ module Ui
4
+ module Command
5
+ class WhisperLock < Command::Base
6
+ def self.description
7
+ 'sets the current chat to to a chosen person'
8
+ end
9
+
10
+ def target
11
+ # get first arg
12
+ command_args[1]
13
+ end
14
+
15
+ def handle
16
+ NodeFinder.find_by_target(target) do |node|
17
+ Display.info "whisper-locked to #{node.alias_name}##{node.uid}"
18
+ _input_factory.whisper_lock_to(node)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -35,7 +35,7 @@ module Meshchat
35
35
 
36
36
  def info(msg)
37
37
  if msg.is_a?(Hash)
38
- message_parts_for(msg) do |time, name, message|
38
+ message_parts_for(msg) do |time, name, message, _|
39
39
  colored_time = (time.to_s + ' ').colorize(:magenta)
40
40
  colored_name = (name + ' ').colorize(:light_black)
41
41
  colored_message = message.colorize(:light_black)
@@ -60,7 +60,7 @@ module Meshchat
60
60
  end
61
61
 
62
62
  def emote(msg)
63
- message_parts_for(msg) do |time, name, message|
63
+ message_parts_for(msg) do |time, name, message, _|
64
64
  colored_time = (time.to_s + ' ').colorize(:magenta)
65
65
  colored_name = (name + ' ').colorize(:light_black)
66
66
  colored_message = message.colorize(:light_black)
@@ -70,7 +70,7 @@ module Meshchat
70
70
  end
71
71
 
72
72
  def chat(msg)
73
- message_parts_for(msg) do |time, name, message|
73
+ message_parts_for(msg) do |time, name, message, _|
74
74
  colored_time = (time.to_s + ' ').colorize(:light_magenta)
75
75
  colored_name = (name + ' ').colorize(:cyan)
76
76
 
@@ -79,12 +79,14 @@ module Meshchat
79
79
  end
80
80
 
81
81
  def whisper(msg)
82
- message_parts_for(msg) do |time, name, message|
82
+ message_parts_for(msg) do |time, name, message, to|
83
83
  colored_time = (time.to_s + ' ').colorize(:magenta).bold
84
- colored_name = (name + ' ').colorize(:light_black).bold
84
+ colored_name = name.colorize(:light_black).bold
85
85
  colored_message = message.colorize(:blue).bold
86
+ colored_to = to.colorize(:blue).bold
86
87
 
87
- print_non_destructively(colored_time + colored_name + colored_message)
88
+ names = "#{colored_name}->#{to} "
89
+ print_non_destructively(colored_time + names + colored_message)
88
90
  end
89
91
  end
90
92
 
@@ -94,8 +96,9 @@ module Meshchat
94
96
  time = msg[:time].strftime('%H:%M:%S')
95
97
  name = msg[:from].to_s
96
98
  message = msg[:message]
99
+ to = msg[:to]
97
100
 
98
- yield(time, name, message)
101
+ yield(time, name, message, to)
99
102
  end
100
103
  end
101
104
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Meshchat
3
- VERSION = '0.11.2'
3
+ VERSION = '0.12.0'
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meshchat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.2
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - L. Preston Sego III
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-11 00:00:00.000000000 Z
11
+ date: 2016-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sqlite3
@@ -316,6 +316,7 @@ files:
316
316
  - lib/meshchat/ui/cli/keyboard_line_input.rb
317
317
  - lib/meshchat/ui/cli/readline_input.rb
318
318
  - lib/meshchat/ui/command.rb
319
+ - lib/meshchat/ui/command/all_chat_lock.rb
319
320
  - lib/meshchat/ui/command/base.rb
320
321
  - lib/meshchat/ui/command/bind.rb
321
322
  - lib/meshchat/ui/command/chat.rb
@@ -326,6 +327,7 @@ files:
326
327
  - lib/meshchat/ui/command/identity.rb
327
328
  - lib/meshchat/ui/command/import.rb
328
329
  - lib/meshchat/ui/command/irb.rb
330
+ - lib/meshchat/ui/command/node_finder.rb
329
331
  - lib/meshchat/ui/command/offline.rb
330
332
  - lib/meshchat/ui/command/online.rb
331
333
  - lib/meshchat/ui/command/ping.rb
@@ -335,6 +337,7 @@ files:
335
337
  - lib/meshchat/ui/command/server.rb
336
338
  - lib/meshchat/ui/command/share.rb
337
339
  - lib/meshchat/ui/command/whisper.rb
340
+ - lib/meshchat/ui/command/whisper_lock.rb
338
341
  - lib/meshchat/ui/display.rb
339
342
  - lib/meshchat/ui/display/base.rb
340
343
  - lib/meshchat/ui/display/manager.rb
@@ -366,6 +369,6 @@ rubyforge_project:
366
369
  rubygems_version: 2.5.1
367
370
  signing_key:
368
371
  specification_version: 4
369
- summary: Meshchat-0.11.2
372
+ summary: Meshchat-0.12.0
370
373
  test_files: []
371
374
  has_rdoc: